实体框架在多对多关系中重复条目
Posted
技术标签:
【中文标题】实体框架在多对多关系中重复条目【英文标题】:Entity Framework duplicate entries in many to many relationship 【发布时间】:2015-11-16 16:34:20 【问题描述】:我已经阅读了很多关于多对多实体框架问题的帖子,并且它再次让人头疼。
Colaborador 有一个 ICollection of Time 和 时间有一个Colaborador的集合
有人说在上下文中添加之前有必要附加子实体(对我不起作用,Pk 错误)。
我正在使用简单的注入器,我的上下文是每个请求的。
我的关联表是这样映射的:
HasMany<Time>(c => c.Times)
.WithMany(t => t.Colaboradores)
.Map(ct =>
ct.MapLeftKey("ColaboradorId");
ct.MapRightKey("TimeId");
ct.ToTable("Receptor");
);
它在数据库中创建关联表。 当我尝试插入 Colaborador(entity) 时,我在其列表中添加了一些 Times(Teams),添加到 DbContext 然后 SaveChanges()。
当我这样做时,它会创建一个新的 Colaborador,在关联表(ID)中正确插入,但也会复制时间。
var colaborador = Mapper.Map<ColaboradorViewModel, Colaborador>(colaboradorVm);
List<TimeViewModel> timesVm = new List<TimeViewModel>();
colaboradorVm.TimesSelecionados.ForEach(t => timesVm.Add(_serviceTime.BuscarPorId(t)));
colaborador.Times = Mapper.Map<ICollection<TimeViewModel>, ICollection<Time>>(timesVm);
函数 BuscarPorId 执行 Find 方法并返回一个时间。
我发现如果我调用 Add 命令,实体也会将孩子的状态标记为已添加,但如果我尝试附加时间或将其状态更改为未更改,我会得到一个主键错误...
foreach (var item in colaborador.Times)
lpcContext.Set<Time>().Attach(item);
//lpcContext.Entry(item).State = EntityState.Unchanged;
有没有办法告诉实体框架不要插入特定的孩子?所以只填充了主表和关联表?
【问题讨论】:
这与多对多关系无关。它总是发生。如果您需要避免添加相关实体,则需要从数据库中检索它们(与添加时使用的上下文相同)或将它们附加到上下文中,然后将 EntityState 设置为 Unchanged @Moho : 附加类型实体失败,因为另一个相同类型的实体已经具有相同的主键值。 @bubi,我使用 Find 方法检索时间,然后将其添加到 Colaborador 的列表中。就在添加上下文之前,我试图附加(就像上面显示的那样),但我得到了 Pk 错误。这不是正确的方法吗? 【参考方案1】:Mapper.Map
创建新的 Time
对象,这些对象未附加到您的上下文,因此您必须将它们附加为 Unmodified
,但附加它们会由于重复 PK 而导致另一个错误,因为您的上下文已经在跟踪Time
实体。使用Find
方法将检索这些跟踪和本地缓存的实体。
查找并使用已附加到您的上下文的实体:
代替:
colaborador.Times = Mapper.Map<ICollection<TimeViewModel>, ICollection<Time>>(timesVm);
用途:
var times = new List<Time>();
var dbSet = lpcContext.Set<Time>();
foreach( var t in timesVm )
var time = dbSet.Find( t.Id );
if( null == time )
time = Mapper.Map<TimeViewModel, Time>( t );
times.Add( time );
collaborador.Times = times;
【讨论】:
Moho,timesVm 已经有我需要的数据,但它在视图模型中(以前使用 _serviceTime.BuscarPorId()... BuscarPorId 执行 Find 方法)。是否真的需要再次为每个 id 做另一个 foreach ?因为在这一层我没有访问 DbSet(我调用服务为我做这件事),但我知道它们是相同的上下文(因为我将它们设置为每个请求) 您已经知道答案了,因为您的代码不起作用;Mapper.Map
创建新的 Time
对象,这些对象未附加到您的上下文,因此您必须将它们附加为 Unmodified
,但由于重复 PK,附加它们会导致另一个错误,因为您的上下文已经在跟踪 @987654331 的原始副本@实体。使用Find
方法将检索这些跟踪和本地缓存的实体。
我终于明白了它是如何工作的,我要感谢@Moho。以上是关于实体框架在多对多关系中重复条目的主要内容,如果未能解决你的问题,请参考以下文章