Boggin
Boggin

Reputation: 3416

Entity Framework 5 add entity and child entities with other foreign key relationships

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

Answers (1)

Boggin
Boggin

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

Related Questions