2

I couldn't find a satisfactory hint for my issue described below. All the results I found refer to EF 4 being unable to solve the problem. I'm using EF 6.1 and the Code First approach.

Here's my class structure:

public class Order 
{
    public List<Pack> Packs { get; set; }   
}

public class Pack
{
     public List<DocumentBase> Documents { get; set; }
}

public abstract class DocumentBase
{
}

public class Document1 : DocumentBase
{
    public List<Document1SpecificClass> D1SpecificObjects { get; set; }
}

Here's the relevant part of the context:

public class MyDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Order>().HasKey(o => o.Key);
        modelBuilder.Entity<Pack>().HasKey(o => o.Key);
        modelBuilder.Entity<DocumentBase>().HasKey(o => o.Key);
        modelBuilder.Entity<Order>().HasMany(o => o.Packs).WithRequired();
        modelBuilder.Entity<Pack>().HasMany(p => p.Documents).WithRequired();

        modelBuilder.Entity<Document1SpecificClass>().HasKey(o => o.Key);
        modelBuilder.Entity<Document1>().HasMany(o => o.D1SpecificObjects);
    }

    public DbSet<Order> Orders { get; set; }
    public DbSet<Pack> Packs { get; set; }
    public DbSet<DocumentBase> Documents { get; set; }
}

I implemented an OrderRepository class that retrieves orders based on various input parameters (order id, order key, invoice etc). I would like to have the D1SpecificObjects collection loaded properly with the corresponding data from the database. An example of a method from OrderRepository:

Order FindByInvoice(string invoice)
{
    using (var dbContext = new SqlDbContext(DBContextName))
    {
        return dbContext.Orders.Where(o => o.Invoice == invoice).Include("Packs.Documents").FirstOrDefault();
    }
}

The assert below fails:

var order = OrderRepository.FindByInvoice("1234asdf");
var document = order.FindDocumentById(123456); // This is a Document1 document
Assert.IsNotNull(document.D1SpecificObjects);

It seems reasonable for the assert to fail, as I didn't instruct EF to load the collection of Document1SpecificClass in document, as I did with the Packs and the Documents for the order, but I cannot find or figure out a reasonable way of informing EF to load these entities.

The solution I found is this:

Order FindByInvoice(string invoice)
{
    using (var dbContext = new SqlDbContext(DBContextName))
    {
        var order = dbContext.Orders.Where(o => o.Invoice == invoice).Include("Packs.Documents").FirstOrDefault();
        if (null != order)
        {
            order.Packs.ForEach(pack =>
                {
                    dbContext.Entry(pack)
                        .Collection(p => p.Documents)
                        .Query()
                        .OfType<Document1>()
                        .Include(doc1 => doc1.D1SpecificObjects)
                        .Load();
                });
        }
        return order;
    }
}

For each pack in the order, I force the loading of the D1SpecificObjects for the documents of type Document1. I'm not very happy with this solution because it clutters the code for the OrderRepository, that should be agnostic to the type of documents. It gets even worse with multiple classes derived from DocumentBase, with their own specific collections. I was under the impression that in EF 6 things would be easier.

Any advice on how to tackle this is welcome.

Thank you.

Paul
  • 1,224
  • 2
  • 14
  • 31
  • Check [This post][1], that might help you. [1]: http://stackoverflow.com/questions/10822656/entity-framework-include-multiple-levels-of-properties – maugusto Jul 18 '15 at 13:35

0 Answers0