如何使用Entity Framework Core配置其他用户定义的数据类型?

3
我正在使用Entity Framework Core 2.1中的脚手架实体。第三方数据库使用了一些我不知道的自定义数据类型(在这里),似乎EF-Core无法识别。
根据Fluent API HasColumnType方法Reverse Enginer:支持类型别名(用户定义的数据类型),应该可以解决此问题。但我不确定它是否仅适用于预配置/内置类型,例如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
有没有其他方法来定义用户自定义的数据类型或以其他方式解决此问题?

1
您可能想要提交新问题来解决此问题。 - bricelam
1
此外,类型别名(又称域)与用户定义类型(UDT)非常不同。 - bricelam
@bricelam 完成 - t3chb0t
@bricelam 我很确定这是一个用户定义的数据类型(在SSMS中显示为此),但您可以在提交的问题中进行检查。我还创建了一个演示来重现它。 - t3chb0t
2
谢谢!我们怀疑这也是一个UDT。不幸的是,在.NET Core上对此的支持有限... - bricelam
1
@bricelam,请看一下我的答案。有一个解决方法。 - t3chb0t
1个回答

1
我找到了一个解决方法。
OnModelCreating 方法的结尾,我只需要移除生成的 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" });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接