实体框架在多对多关系中重复条目

时间:2015-11-16 16:34:20

标签: c# asp.net-mvc entity-framework

我已经阅读了许多关于实体框架问题的帖子,其中包含很多对许多人的问题,并且它再次成为了一个痛苦的问题。

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(实体)时,我在其列表中添加一些Times(Teams),添加到DbContext然后SaveChanges()。

当我这样做时,它会创建一个新的Colaborador,在关联表(ids)中正确插入,但也复制时间。

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方法并返回Time。

我已经发现如果我调用Add命令,实体会将子状态标记为Added,但是如果我尝试附加Time或将状态更改为Unchanged,我会得到一个关键错误......

foreach (var item in colaborador.Times)
{                
    lpcContext.Set<Time>().Attach(item);
    //lpcContext.Entry(item).State = EntityState.Unchanged;
}

有没有办法告诉实体框架不插入特定的孩子?那么只填充主表和关联表吗?

1 个答案:

答案 0 :(得分: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;