抽象类与派生类条件映射问题导致EF6 SaveChanges报错
EF6中OfType查询与SaveChanges报错的解决方案
问题场景
使用EF6的TPH(每个层次结构一张表)继承映射模式,基类Collection为抽象类,子类NewsCollection继承自它,通过OfType<NewsCollection>查询实体并修改后,调用SaveChanges抛出MappingException,错误提示Condition member 'Collection.COL_TYPE' with a condition other than 'IsNull=False' is mapped。
错误原因
ColType字段同时被设置为复合主键的成员,又通过Map<NewsCollection>(co => co.Requires("ColType").HasValue(19999))作为子类的鉴别器条件,EF6不允许主键字段同时作为带固定值的鉴别器条件,导致映射视图生成冲突。
解决方案
1. 恢复子类的鉴别器属性重写
在NewsCollection类中重写ColType属性,固定返回鉴别器值19999,确保实体实例的鉴别器值正确:
public class NewsCollection : Collection { public override int ColType => 19999; }
2. 修改映射配置,使用TPH标准鉴别器配置
在CollectionDbMap中,替换原有的Map<NewsCollection>配置,改用HasDiscriminator来定义鉴别器字段和子类对应值:
public class CollectionDbMap : EntityTypeConfiguration<Collection> { public CollectionDbMap() { ToTable("WWW_COLLECTION"); HasKey(co => new { co.ColType, co.UserSn, co.ItemId }); Property(co => co.ColType).HasColumnName("COL_TYPE"); Property(co => co.UserSn).HasColumnName("USER_SN"); Property(co => co.ItemId).HasColumnName("ITEM_ID"); Property(co => co.CreatedBy).HasColumnName("CREATED_BY"); Property(co => co.CreatedDate).HasColumnName("CREATED_DATE"); Property(co => co.Title).HasColumnName("TITLE"); // 配置TPH鉴别器 HasDiscriminator<int>("COL_TYPE") .HasValue<NewsCollection>(19999); } }
3. 验证查询与保存逻辑
修改后,db.Collections.OfType<NewsCollection>()会自动通过鉴别器值筛选出NewsCollection类型的实体,修改实体属性后调用SaveChanges时,EF6能正确识别实体类型并生成对应的更新语句,不会再出现映射冲突。
修改后的完整代码示例
using System; using System.Data.Entity; using System.Data.Entity.ModelConfiguration; using System.Linq; namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { try { var db = new ToutiaoDbContext(); var query = db.Collections.OfType<NewsCollection>(); var list = query.ToList(); var entity = list.FirstOrDefault(); if(entity != null) // 增加空判断避免空引用 { entity.Title = "title123"; var res = db.SaveChanges(); Console.WriteLine(res); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } } public class ToutiaoDbContext : DbContext { public ToutiaoDbContext() : base("xxx") { } public DbSet<Collection> Collections { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new CollectionDbMap()); base.OnModelCreating(modelBuilder); } } public class CollectionDbMap : EntityTypeConfiguration<Collection> { public CollectionDbMap() { ToTable("WWW_COLLECTION"); HasKey(co => new { co.ColType, co.UserSn, co.ItemId }); Property(co => co.ColType).HasColumnName("COL_TYPE"); Property(co => co.UserSn).HasColumnName("USER_SN"); Property(co => co.ItemId).HasColumnName("ITEM_ID"); Property(co => co.CreatedBy).HasColumnName("CREATED_BY"); Property(co => co.CreatedDate).HasColumnName("CREATED_DATE"); Property(co => co.Title).HasColumnName("TITLE"); // 配置TPH鉴别器 HasDiscriminator<int>("COL_TYPE") .HasValue<NewsCollection>(19999); } } public abstract class Collection { public virtual int ColType { get; protected set; } public int UserSn { get; set; } public int ItemId { get; set; } public int CreatedBy { get; set; } public DateTime CreatedDate { get; set; } public string Title { get; set; } } public class NewsCollection : Collection { public override int ColType => 19999; } }
内容的提问来源于stack exchange,提问作者huhmuren heriid
相关产品推荐
相关产品推荐

