【问题标题】:How do I configure other user defined data-type with Entity Framework Core?如何使用 Entity Framework Core 配置其他用户定义的数据类型?
【发布时间】:2018-12-19 08:47:38
【问题描述】:

我在 Entiy Framework Core 2.1 中使用脚手架实体。第 3 方数据库使用了一些 EF-Core 似乎无法识别的非用户定义数据类型 (that I didn't know about)。

根据The Fluent API HasColumnType MethodReverse Enginer: Support type aliases (user-defined data types) 这应该可以工作。但是,我不确定是否仅适用于 Name 等预配置/内置类型或任何类型。

引擎生成这个

entity.Property(e => e.Status).HasColumnType("Enumeration");

对于Enumeration:smallint,但将其转换为 SQL 效果不佳,因此会抛出 SqlException

Class         16  byte
LineNumber    1   int
Message       "Type Enumeration is not a defined system type."    string
Number        243 int
Procedure     ""  string
Server        "..."   string
Source        ".Net SqlClient Data Provider"  string
State         2   byte

有没有办法定义其他用户定义的数据类型或以任何其他方式解决这个问题?

【问题讨论】:

  • 您可能想submit a new issue 了解此事。
  • 此外,类型别名(也称为域)与用户定义类型 (UDT) 非常不同。
  • @bricelam done
  • 谢谢!我们怀疑它也是一个UDT。不幸的是,这些对 .NET Core 的支持有限......
  • @bricelam 看看my answer。有一种解决方法。

标签: c# tsql entity-framework-core sql-server-2014


【解决方案1】:

我找到了解决方法。

OnModelCreating 方法的 and 处,我将删除生成的 ColumnType 注释:

  modelBuilder
    .Entity(typeof(MyEntity))
    .Property(nameof(MyEntity.Status))
    .Metadata
    .RemoveAnnotation("Relational:ColumnType");

一个小的帮助函数,它遍历所有实体并自动从所有具有它的属性中删除该注释,现在应该足够了。

public static class ModelBuilderExtensions
{
    public static ModelBuilder RemoveAnnotations<TDbContext>(this ModelBuilder modelBuilder, TDbContext context, string name, IList<string> values) where TDbContext : DbContext
    {
        var bindingFlags = 
            BindingFlags.Instance | 
            BindingFlags.Public | 
            BindingFlags.DeclaredOnly;

        var entityMethod =
            typeof(ModelBuilder)
                .GetMethods()
                .Single(m =>
                    m.Name == nameof(ModelBuilder.Entity) &&
                    m.GetGenericArguments().Length == 1 &&
                    m.GetParameters().Length == 0
                )
                .GetGenericMethodDefinition();

        foreach (var contextProperty in typeof(TDbContext).GetProperties(bindingFlags))
        {
            var entity =
                contextProperty
                    .PropertyType
                    .GetGenericArguments()
                    .SingleOrDefault();

            if (entity is null)
            {
                continue;
            }

            // Only the generic overload returns properties. The non-generic one didn't work.
            var generitcEntityMethod = entityMethod.MakeGenericMethod(entity);

            foreach (var property in entity.GetProperties(bindingFlags))
            {
                var entityTypeBuilder = (EntityTypeBuilder)generitcEntityMethod.Invoke(modelBuilder, null);

                if (entityTypeBuilder.Metadata.FindProperty(property) is null)
                {
                    continue;
                }

                var annotation = 
                    entityTypeBuilder
                        .Property(property.Name)
                        .Metadata
                        .FindAnnotation(name);

                if (values.Contains(annotation?.Value))
                {
                    entityTypeBuilder
                        .Property(property.Name)
                        .Metadata
                        .RemoveAnnotation(name);
                }
            }
        }
        return modelBuilder;
    }
}

用法:

modelBuilder.RemoveAnnotations(this, "Relational:ColumnType", new[] { "Enumeration" });

【讨论】:

    猜你喜欢
    • 2019-05-12
    • 1970-01-01
    • 2021-04-17
    • 2023-04-09
    • 2018-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多