问题描述:

My problem is to save existing objects that are part of a many-to-many relationship in a code-first database with EF6.

I am receiving objects from a web service and they look (simplified) like:

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. 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.

The solutions I found to this problem is to set the Contract in the dbContext to 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.

Is there any way to tell EF that my two different Contract-objects actually are the same?

网友答案:

Is there any way to tell EF that my two different Contract-objects actually are the same?

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.

So the only solution is to replace all same id contract instances by a single one.

Or simpler: create an explicit entity representing the N:N relation and then simply build a list to insert as follows:

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