I'm using Entity Framework 4.4 and I have a One-To-Many relationship model like this:
class Item {
public string keyPart1 { get; set; }
public string keyPart2 { get; set; }
public virtual Container container { get; set; }
public string ContainerId { get; set; }
}
// Idea is that many Items will be assigned to a container
class Container {
public string ContainerId { get; set; }
private ICollection<Item> _Items;
public virtual ICollection<Item> As
{
get { return _Items ?? (_Items = new HashSet<A>()); }
protected set { _Items = value; }
}
}
Now, here's the DbContext:
public class StorageContext : DbContext
{
public DbSet<Item> Items { get; set; }
public DbSet<Bucket> Buckets { get; set; }
public override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Item>().HasKey( i => new { i.keyPart1, i.keyPart2 } ).HasRequired( i => i.Container );
}
}
Now, supposing I have N Item instances. Each Item belongs to a container, which contains multiple item instances, each of which belongs to a container, and so the model recurses endlessly.
I want to then cycle through my current list of Item instances and add each to the db context:
foreach (var i in LocalItemList)
{
IDbSetExtensions.AddOrUpdate<Item>(db.Items, i);
}
dbContext.SaveChanges();
The problem that I can't figure out is how to tell the context to AddOrUpdate the Container so that I don't get primary key duplicate exceptions. At some point we'll run into an Item that has the same Container as another, but I'll get a duplicate primary key exception on SaveChanges().
If I Add a Container to the DbSet, are the Items added to the Set as well? How can I make that an AddOrUpdate instead?
I am not sure if you want to insert the related
Containers into the database along with theItems, or if you only want to create a relationship to already existingContainers. The possible case that theContainerentities do not exist in the database and in your object graph you only have oneContainerinstance per key (multiple references to those instances are allowed) should not be a problem at all and a simple code like......should actually work without exception. So, you probably have one of the following two situations which would explain the primary key constraint violation:
The
Containerentities already exist in the database and in your object graph you only have oneContainerinstance per key (multiple references to those instances are allowed again). This is the easy case and you can solve it by using:If you have multiple
Containerinstances for the same key this won't work and throw an "...an object with the same key already exists in the ObjectContext..." (or similar) exception. It also won't work if theContainers do not exist yet in the database (you'll probably get a foreign key constraint violation then).If you have multiple
Containerobject instances with the same key in your object graph you must replace the duplicates by one unique instance per key before you attach or add the entities to the context. To make this process simpler I would remove the circular references first and then use theLocalcollection to figure out if aContainerwith the same key is already attached: