Entity Framework对接结构相似的差异数据库时能否使用实体类继承?
方案1:字段条件映射(最便捷,无需修改实体结构)
EF Core支持在配置实体的时候,根据当前上下文连接的数据库标识来决定是否映射某个字段,完全不需要新增父类。
你可以给DbContext加个标识属性,比如public bool IsDB2 { get; set; },在构造上下文的时候给这个属性赋值,然后在CreateModel方法里加判断:
public static void CreateModel(EntityTypeBuilder<Article> p_etbTable, bool isDB2) { // 表名 p_etbTable.ToTable("T_Article"); // 主键 p_etbTable.HasKey(t => new { t.ArtReference }).HasName("PK_ARTREF_T_ARTICLE"); // 公共字段配置 p_etbTable.Property(t => t.ArtReference).IsRequired(); p_etbTable.Property(t => t.ArtReference).HasColumnName("Ar_Ref"); p_etbTable.Property(t => t.ArtReference).HasColumnType("varchar(19)"); p_etbTable.Property(t => t.ArtReference).HasMaxLength(19); p_etbTable.Property(t => t.ArtDesignation).HasColumnName("Ar_Desi"); p_etbTable.Property(t => t.ArtDesignation).HasColumnType("varchar(69)"); p_etbTable.Property(t => t.ArtDesignation).HasMaxLength(69); // 仅非DB2数据库映射ArtType字段 if(!isDB2) { p_etbTable.Property(t => t.ArtType).HasColumnName("Ar_Type"); p_etbTable.Property(t => t.ArtType).HasColumnType("varchar(35)"); p_etbTable.Property(t => t.ArtType).HasMaxLength(35); } else { // DB2环境下忽略该字段,不会参与SQL生成 p_etbTable.Ignore(t => t.ArtType); } }
在上下文的OnModelCreating里调用这个方法的时候,把当前上下文的IsDB2属性传进去就行。DB2环境下查询的时候,ArtType会自动赋值为null,不会抛出找不到列的异常。
方案2:如果坚持用继承结构
你提到的EntityTypeBuilder<Article>转EntityTypeBuilder<LimitedArticle>的需求,可以通过抽离公共配置的泛型方法实现,不需要强制类型转换:
首先定义父类LimitedArticle:
public class LimitedArticle { public string ArtReference { get; set; } public string ArtDesignation { get; set; } public static void CreateLimitedModel<T>(EntityTypeBuilder<T> p_etbTable) where T : LimitedArticle { // 公共字段配置 p_etbTable.HasKey(t => new { t.ArtReference }).HasName("PK_ARTREF_T_ARTICLE"); p_etbTable.Property(t => t.ArtReference).IsRequired(); p_etbTable.Property(t => t.ArtReference).HasColumnName("Ar_Ref"); p_etbTable.Property(t => t.ArtReference).HasColumnType("varchar(19)"); p_etbTable.Property(t => t.ArtReference).HasMaxLength(19); p_etbTable.Property(t => t.ArtDesignation).HasColumnName("Ar_Desi"); p_etbTable.Property(t => t.ArtDesignation).HasColumnType("varchar(69)"); p_etbTable.Property(t => t.ArtDesignation).HasMaxLength(69); } } public class Article : LimitedArticle { public string ArtType { get; set; } public static void CreateModel(EntityTypeBuilder<Article> p_etbTable) { p_etbTable.ToTable("T_Article"); // 调用父类公共配置 LimitedArticle.CreateLimitedModel(p_etbTable); // 配置子类独有字段 p_etbTable.Property(t => t.ArtType).HasColumnName("Ar_Type"); p_etbTable.Property(t => t.ArtType).HasColumnType("varchar(35)"); p_etbTable.Property(t => t.ArtType).HasMaxLength(35); } }
访问DB2的时候,直接用LimitedArticle作为实体查询即可,访问DB1的时候用Article即可,不会出现类型转换错误。
方案3:字段级懒加载(不推荐)
EF Core支持字段级懒加载,但需要给属性加virtual修饰,还要启用懒加载代理,这种方式对于固定缺列的场景完全没必要,还会增加额外的性能开销,而且查询时依然会触发列存在性校验,解决不了缺列抛出的异常,不建议采用这个思路。
内容的提问来源于stack exchange,提问作者Jean-David Lanz
相关产品推荐
相关产品推荐

