Reputation: 3416
I'm using Entity Framework (EF) 5 Code First.
I've a self-referencing object, let's call it Demo
:
public class Demo
{
public int Id;
public string Name;
public Demo Parent;
public ICollection<Demo> Children;
public Item Item;
}
This has a reference to another object, Item
:
public class Item
{
public int Id;
public string Name;
public Item Parent;
public ICollection<Item> Children;
}
Yes, it's also self-referencing but this shouldn't matter. The database now has a foreign key based on an Item_Id
that was added to the Demo
table by the database migration. The database is pre-populated with a set of Item
records (it's a limited set).
My context has mapped this nicely to the database and I'm doing a large data insertion of new records. There's another bit of code that is filling the objects with data. This is the actual import through EF:
public void ImportDemo(IEnumerable<Demo> demos)
{
var context = this.UnitOfWork.MyApplicationContext;
foreach (var demo in demos)
{
this.DataSet.Add(demo);
context.Entry(demo).State = EntityState.Added;
}
// NOTE: expecting an empty db.
context.SaveChanges();
}
My DbModelBuilder has the following:
modelBuilder.Entity<Demo>()
.HasOptional(p => p.Parent)
.WithMany(p => p.Children);
modelBuilder.Entity<Item>()
.HasOptional(p => p.Parent)
.WithMany(p => p.Children);
I can import the Demo
entities successfully, and the child Demo
entities, but each of the child Demo
entities is creating a new Item
in the database rather than just linking up to the existing Item
. Parent Demo
entities don't have Item
records, they are null.
How do I make sure that the child Demo
entities link to the existing Item
records rather than creating new ones?
Upvotes: 0
Views: 1662
Reputation: 3416
The whole structure is set up in a business layer and mapped (AutoMapper) to the models in question.
The Item
objects are in the DbContext.IDbSet<Item>.Local
collection but the dummy Items
in the model need to be reset with the Item
objects in the local collection as follows.
public void ImportDemo(IEnumerable<Demo> demos)
{
foreach (var demo in demos)
{
foreach (var child in demo.Children)
{
child.Item =
dbContext.Items.Local.First(p => p.Id == child.Item.Id)
}
dbContext.Set<Demo>.Add(demo);
}
dbContext.SaveChanges();
}
I tried using Attach()
but it didn't behave how I expected it to from the MSDN documentation.
Upvotes: 0