简体   繁体   English

EF6多对多插入

[英]EF6 Many to many Insert

My problem is to save existing objects that are part of a many-to-many relationship in a code-first database with EF6. 我的问题是使用EF6将属于多对多关系的现有对象保存在代码优先的数据库中。

I am receiving objects from a web service and they look (simplified) like: 我从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; } 
}

I have a code-first database and set the relationship with: 我有一个代码优先的数据库,并设置以下关系:

        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");
            });

When I get a list of cars I can save the first car and EF creates the relation table and the contracts successfully. 得到汽车清单后,我可以保存第一辆汽车,EF会成功创建关系表和合同。 On the second car the save fails saying " constraint failed UNIQUE constraint failed: Contracts.ContractId ", since I'm trying to insert a Contract with the same Id as an already existing Contract. 在第二辆车的保存失败说“ 约束失败UNIQUE约束失败:Contracts.ContractId”,因为我想插入一个Contract具有相同Id为已经存在的合同。

The solutions I found to this problem is to set the Contract in the dbContext to Attached: 我发现此问题的解决方案是将dbContextContract设置为Attached:

foreach (var contract in car.Contracts)
{
    context.Contract.Attach(contract);
}

This throws the same exception as the previous save. 这将引发与先前保存相同的异常。 When I try to modify the Contract-list of the second car I get a NotSupportedException , the only solution I can think of is recreating the car objects and attach the same Contract-object to them, which seems unnecessarily complicated. 当我尝试修改第二辆汽车的合同清单时,我得到一个NotSupportedException ,我能想到的唯一解决方案是重新创建汽车对象并将相同的Contract对象附加到它们,这似乎不必要地复杂。

Is there any way to tell EF that my two different Contract-objects actually are the same? 有没有办法告诉EF我的两个不同的合同对象实际上是相同的?

Is there any way to tell EF that my two different Contract-objects actually are the same? 有没有办法告诉EF我的两个不同的合同对象实际上是相同的?

The only way is they actually are the same object. 唯一的方法是它们实际上是同一对象。 If they are different instances even having all the same data EF won't recognize them as same entity. 如果它们是不同的实例,那么即使具有所有相同的数据EF也不会将它们识别为同一实体。

So the only solution is to replace all same id contract instances by a single one. 因此,唯一的解决方案是用一个实例替换所有相同的id合约实例。

Or simpler: create an explicit entity representing the N:N relation and then simply build a list to insert as follows: 或更简单:创建一个表示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}));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM