代码之家  ›  专栏  ›  技术社区  ›  t3chb0t

如何使用实体框架核心配置其他用户定义的数据类型?

  •  2
  • t3chb0t  · 技术社区  · 7 年前

    我正在使用带有EntityFrameworkCore2.1的架式实体。第三方数据库使用一些未加密的定义数据类型( that I didn't know about )这似乎没有得到英孚核心认可。

    根据 The Fluent API HasColumnType Method Reverse 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
    

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

    1 回复  |  直到 7 年前
        1
  •  1
  •   t3chb0t    7 年前

    我找到了一个解决办法。

    在和的 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" });