Christoph Fink
Christoph Fink

Reputation: 23113

Query base type definiton as derived type using Entity Framework

I have the following POCOs (using Code First and EF 6.0.0 alpha 3):

public class RevBase
{
    [Key]
    public int Id{ get; set; }
}

public class ItemBase
{
    [Key]
    public int Id { get; set; }

    public List<RevBase> Revs { get; set; }
}

public class RevDev : RevBase
{
    public string Content { get; set; }
}

public class ItemDev : ItemBase
{
    public string Title { get; set; }
}

and the following context

public class MyContext : DbContext
{
    DbSet<ItemDev> Items { get; set; }
}

Now I would like to query context.Items.Include(i => i.Revs) but tell the EF somehow it should load the Revs as RevDev not RevBase.

Is that possible or do I need to load them as RevBase and make another query to get the according RevDev instances?

One other way I tried was creating a second relation from RevDev to ItemDev, but then EF also creates a second foreign key column in the DB which is not really necessary...

Upvotes: 1

Views: 857

Answers (2)

Slauma
Slauma

Reputation: 177163

load the Revs as RevDev not RevBase

If a given RevBase is not a RevDev you can't load it as RevDev. (Not every animal is a dog. You cannot make every animal a dog, some are cats.)

Actually, what you need, I believe, is a filter by the type, which is generally a problem when using Include because it doesn't support any filtering at all. I see two options you have:

  • Use explicit loading (which supports filtering):

    var items = context.Items.ToList();
    foreach (var item in items)
        context.Entry(item).Collection(i => i.Revs).Query()
            .Where(r => r is RevDev)
            .Load();
    

    These are 1 + N separate database queries.

  • Use a projection:

    var items = context.Items
        .Select(i => new
        {
            Item = i,
            RevDevs = i.Revs.Where(r => r is RevDev)
        })
        .AsEnumerable()
        .Select(a => a.Item)
        .ToList();
    

    This is only one database query. Automatic relationship fixup should populate the Item.Revs collection with the loaded RevDevs.

Upvotes: 1

Christoph Fink
Christoph Fink

Reputation: 23113

Just found out that Entity Framework does that by default. I had another error in my code why it did not work...

Upvotes: 0

Related Questions