0

Brief background:

Using Database First/Code Only (though I don't think it should matter)

The basic setup is this:

public class MyContext : DbContext
{
    public DbSet<MyClass_MyClasses> MyClass_MyClasses { get; set; }
    public DbSet<MyClass> MyClasses { get; set; }
}

public class MyClass_MyClasses
{
    [Key]
    [Column(Order = 0)]
    public Guid ParentId { get; set; }

    [Key]
    [Column(Order = 1)]
    public Guid MyClassId { get; set; }

    public int Sequence { get; set; }

    public virtual MyClass MyClass { get; set; }
}

public class MyClass
{
    [Key]
    public Guid Id { get; set; }

    public string Url { get; set; }

    // ...
}

// interface part isn't important, I'm just using the wrapper to
// combine data from different sources to eventually be passed to a Json service
public class EntityWrapper : ISomeInterface
{
    public MyClass_MyClasses Relation { get; set; }

    public string Url { get { return MyClass_MyClasses.MyClass.Url; } }

    // ... some other stuff

    public EntityWrapper() { }
}

The problem seems to be that .Include(Func<,>) is not being honored when I do something like this:

using(MyContext context = new MyContext())
{

    IEnumerable<EntityWrapper> wrappedResults =
        from relation in context.MyClass_MyClasses.Include(mm => mm.MyClass)
        orderby  relation.Sequence ascending
        select new EntityWrapper { Relation = relation };

    foreach(EntityWrapper wrapper in wrappedResults)
    {
        // always thrown
        if(wrapper.Relation.MyClass == null)
            throw new WtfException("But I specified .Include?");
    }
}

I've been working around it by instead of selecting to the EntityWrapper, selecting to the MyClass_MyClasses and then in my foreach just assigning a local variable = new EntityWrapper { ... } which works.

My question is: Am I doing something incorrectly? or is this a bug with EF?

Also: apologies in advance, this is a paraphrase of actual code so some of the things might not be exactly the same... If this isn't reproducible I'll try and copy more direct versions of my classes.

Thanks in advance.

6
  • @Jeroen: 4.1.10715.0 (from Nuget) Commented Aug 17, 2011 at 1:28
  • have you mapped public virtual MyClass MyClass property using model builder? Commented Aug 17, 2011 at 1:30
  • @Eranga: I used the annotations for ForeignKey on the property and it made no difference? shouldn't that and the .Include be enough? I didn't mention specifically in the question but I'm using Db First/Code only because I have some specifics I can't qualify using EF in the tables, though they should not interfere... Commented Aug 17, 2011 at 1:36
  • @Anthony the way you test whether Include works is incorrect. if you have configured MyClass property correctly, it would have been lazy loaded. Commented Aug 17, 2011 at 1:41
  • @Eranga: I tried turning off lazy loading and received same results. This seems to indicate that .Include should have brought along the MyClass property with the initial query: msdn.microsoft.com/en-us/library/gg671236%28v=vs.103%29.aspx Commented Aug 17, 2011 at 1:48

2 Answers 2

1

Include and projection are disjunctive = once you use projection Include is not used automatically. Try this:

var results =
    from relation in context.MyClass_MyClasses.Include(mm => mm.MyClass)
    orderby  relation.Sequence ascending
    select relation;

foreach(EntityWrapper wrapper in results.ToList()
                                        .Select(r => new EntityWrapper { Relation = r }))
{
    // always thrown
    if(wrapper.Relation.MyClass == null)
        throw new WtfException("But I specified .Include?");
}

You can also try to use AsEnumerable instead of ToList

Sign up to request clarification or add additional context in comments.

3 Comments

+1 Is there some reference where I can see why they are disjunctive? I kind of understand why it would be difficult to do, but it works when using two separate IEnumerable<>s
Simply that is how EF works. Include is used only if you return entity itself.
Seems like they should have been able to honor that query pattern, but ah well I ended up doing it a different way... Bummer.
0

try to remove the virtual keyword.

public virtual MyClass MyClass { get; set; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.