EF6多对多插入

时间:2016-02-19 08:12:20

标签: c# entity-framework

我的问题是在使用EF6的代码优先数据库中保存属于多对多关系一部分的现有对象。

我从Web服务接收对象,它们看起来像(简化),如:

public class Car
{
    [DataMember]
    public virtual string CarId { get; set; }

    [DataMember]
    public virtual ICollection<Contract> Contracts { get; set; }
}

public class Contract
{   
    [DataMember]
    public virtual string ContractId { get; set; }

    [DataMember]
    public virtual ICollection<Car> Cars { get; set; } 
}

我有一个代码优先的数据库并设置关系:

        modelBuilder.Entity<Contract>().HasKey(t => new {t.ContractId});
        modelBuilder.Entity<Car>().HasKey(t => new {t.CarId})
            .HasMany(c => c.Contracts)
            .WithMany(c => c.Cars)
            .Map(x =>
            {
                x.ToTable("CarContracts");
                x.MapLeftKey("CarId");
                x.MapRightKey("ContractId");
            });

当我得到汽车列表时,我可以保存第一辆汽车,EF会成功创建关系表和合同。在第二辆车上,保存失败说“约束失败UNIQUE约束失败:Contracts.ContractId ”,因为我正在尝试插入ContractId相同的Contract已经存在的合同。

我发现此问题的解决方案是将dbContext中的foreach (var contract in car.Contracts) { context.Contract.Attach(contract); } 设置为附加:

NotSupportedException

这会抛出与上一次保存相同的异常。当我尝试修改第二辆车的合同清单时,我得到一个<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="dropdown"> <a href="#" ng-click="$event.preventDefault()" title="Timesheet" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-time"></span> Timesheet <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a ui-sref="AddTime" title="Add time" href="/Timesheet/AddTime/">Add time</a></li> <li><a ui-sref="ApproveTime" title="Approve time" href="/Timesheet/ApproveTime">Approve time</a></li> <li><a ui-sref="Projects" title="Projects" href="/Timesheet/Admin/Projects">Projects</a></li> <li><a ui-sref="BudgetCode" title="Budget Code" href="/Timesheet/Admin/BudgetCode">Budget Code</a></li> <li><a ui-sref="WorkCode" title="Work Code" href="/Timesheet/Admin/WorkCode">Work Code</a></li> <li><a ui-sref="Functions" title="Functions" href="/Timesheet/Admin/Functions">Functions</a></li> <li><a ui-sref="WorkStreams" title="Work Streams" href="/Timesheet/Admin/WorkStreams">Work Streams</a></li> <li><a ui-sref="EmployeeResource" title="Employees" href="/Timesheet/Admin/EmployeeResource">Employees</a></li> </ul> </li> </ul> </div> ,我能想到的唯一解决方案是重新创建汽车对象并将相同的契约对象附加到它们,这似乎不必要地复杂化。 / p>

有没有办法告诉EF我的两个不同的合同对象实际上是一样的?

1 个答案:

答案 0 :(得分:1)

  

有没有办法告诉EF我的两个不同的Contract-object   实际上是一样的吗?

唯一的方法是它们实际上是同一个对象。如果它们是不同的实例,即使具有所有相同的数据,EF也不会将它们识别为同一实体。

所以唯一的解决方案是用一个替换所有相同的id合同实例。

或者更简单:创建一个表示N:N关系的显式实体,然后简单地构建一个列表,插入如下:

var toInsert = new List<CarContract>();
foreach(var car in cars)
{
    toInsert.AddRange(car.Select(x=>new CarContract {CarId=car.Id,ContractId=x.Id}));
}