Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework ObjectQuery.Include()

I have an object with two objects as properties (User, PrimaryNode), both could potentially be null, see below:

public class Item
{
    [Key]
    public int ItemId { get; set; }
    public string ItemName { get; set; }
    public Node PrimaryNode { get; set; }
    public User User { get; set; }
}

I'm using Entity Framework 6 to populate the Item object and using chained includes to populate the PrimaryNode and User objects within it.

When the first chained Include has a null object then the whole object returns as null, for example:

using (var db = new MyContext())
{
    var item = db.Items.Include(i => i.User).Include(n => n.PrimaryNode).FirstOrDefault(i => i.ItemId == id);
}

If in the above example i.User is null then the item variable is null. Whats the best way of populating both the sub-objects in a way that if a sub-object is null then the parent object and the other sub-object will still be populated?

like image 496
Andy E Avatar asked Jan 06 '16 18:01

Andy E


People also ask

What does IQueryable include do?

Include(IQueryable, String)Specifies the related objects to include in the query results.

What is use of include in LINQ?

LINQ include helps out to include the related entities which loaded from the database. It allows retrieving the similar entities to be read from database in a same query. LINQ Include() which point towards similar entities must read from the database to get in a single query.

What is include in C#?

Because the Include method returns the query object, you can call this method multiple times on an ObjectQuery<T> to specify multiple paths for the query, as in the following example: C# Copy.


2 Answers

I don't think your issue is due to the Include calls. According with the documentation:

This extension method calls the Include(String) method of the IQueryable source object, if such a method exists. If the source IQueryable does not have a matching method, then this method does nothing.

In other words is going to be translated to:

 var item = db.Items.Include("User").Include("PrimaryNode").FirstOrDefault(i => i.ItemId == id);

My question is, are you sure you have an Item with that id properly related with existing rows in Users and PrimaryNodes tables in your DB?. When you call Include method at the end is going to be translated to a join, so if the FK of your relationship doesn't match with the PK that reference, your query should not return what you are expecting.

Anyways, if you want to try another variant to load related properties you can use Explicit Loading:

var item = db.Items.FirstOrDefault(i => i.ItemId == id);
context.Entry(item).Reference(p => p.PrimaryNode).Load(); 
context.Entry(item).Reference(p => p.User).Load();
like image 128
octavioccl Avatar answered Sep 21 '22 17:09

octavioccl


I think it would be better if you use Lazy loading int his situation. Just make the User and PrimaryNode virtual:

public class Item
{
   [Key]
   public int ItemId { get; set; }
   public string ItemName { get; set; }
   public virtual Node PrimaryNode { get; set; }
   public virtual User User { get; set; }
}

And then:

var db = new MyContext();
var item = db.Items.FirstOrDefault(i => i.ItemId == id);
like image 20
Salah Akbari Avatar answered Sep 22 '22 17:09

Salah Akbari