Entity Framework ObjectQuery.Include ()

I have an object with two objects as properties ( User , PrimaryNode ), both potentially could 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 am using Entity Framework 6 to populate the Item object and use PrimaryNode to populate the PrimaryNode and User objects inside it.

When the first related Include has a null object, then the whole object is returned 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 i.User is null in the above example, then the Item variable is null. What is the best way to populate both sub-objects in such a way that if the sub-object is null then the parent object and the other sub-object will still be filled?

+6
source share
3 answers

I do not think your problem is caused by Include calls. According to the documentation:

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

In other words, it will be translated into:

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

My question is: are you sure that you have an Item with this identifier appropriately associated with existing rows in the Users and PrimaryNodes in your database ?. When you call the Include method at the end, it will be transferred to the connection, so if the FK of your relationship does not match the PK reference, your request should not return what you expect.

In any case, if you want to try another option for loading related properties, you can use Explicit Download :

 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(); 
+1
source

I think it would be better if you used Lazy to load his situation. Just create virtual files User and PrimaryNode :

 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); 
+1
source

As already mentioned, I think your problem is not related to Includes. However, I think the following method matters. This is functionally equivalent to what you are already doing with chained inclusions, but I think it has several advantages, including with the goal of making the code understandable to the user.

Attachments can be placed in extension methods:

 using System.Data.Entity; using System.Linq; namespace Stackoverflow { public static class EntityExtensions { public static IQueryable<Item> IncludePrimaryNode(this IQueryable<Item> query) { // eager loading if this extension method is used return query.Include(item => item.PrimaryNode); } public static IQueryable<Item> IncludeUser(this IQueryable<Item> query) { // eager loading if this extension method is used return query.Include(item => item.User); } } } 

Then you can use the extensions as follows:

 using (var db = new MyContext()) { var itemQuery = db.Items.IncludeUser(); itemQuery = itemQuery.IncludePrimaryNode(); var item = itemQuery.FirstOrDefault(i => i.Id == 1); } 

This is just another way to do the same, but I like the clarity that it adds to the code.

0
source

All Articles