[英]Entity Framework ObjectQuery.Include()
I have an object with two objects as properties ( User
, PrimaryNode
), both could potentially be null, see below: 我有一个对象,其中有两个对象作为属性(
User
, PrimaryNode
),都可能为null,请参见下文:
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. 我正在使用Entity Framework 6填充
Item
对象,并使用链式包含在其中填充PrimaryNode
和User
对象。
When the first chained Include has a null object then the whole object returns as null, for example: 当第一个链接的Include具有空对象时,则整个对象将返回空值,例如:
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. 如果在上面的示例中
i.User
为null,则item
变量为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? 以某种方式填充两个子对象的最佳方法是:如果一个子对象为null,则仍将填充父对象和另一个子对象?
I think it would be better if you use Lazy loading int his situation. 我认为如果您在他的情况下使用Lazy loading会更好。 Just make the
User
and PrimaryNode
virtual: 只需将
User
和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);
I don't think your issue is due to the Include
calls. 我认为您的问题不是由于
Include
通话引起的。 According with the documentation : 根据文档 :
This extension method calls the Include(String) method of the
IQueryable
source object, if such a method exists.如果存在这样的方法,则此扩展方法将调用
IQueryable
源对象的Include(String)方法。 If the sourceIQueryable
does not have a matching method, then this method does nothing .如果源
IQueryable
没有匹配方法,则此方法不执行任何操作 。
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?. 我的问题是,您确定您有一个ID与数据库中
Users
和PrimaryNodes
表中的现有行正确相关的Item
吗? 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. 当您在最后调用
Include
方法将转换为联接时,因此,如果关系的FK与该引用的PK不匹配,则查询不应返回期望的结果。
Anyways, if you want to try another variant to load related properties you can use Explicit Loading : 无论如何,如果您想尝试另一个变体来加载相关属性,则可以使用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();
As others have mentioned, I think your issue is not due to the Includes. 正如其他人所提到的,我认为您的问题并非归因于Includes。 However, I think the following method has value.
但是,我认为以下方法有价值。 It is functionally equivalent to what you are already doing with the chained includes, but I think it has several benefits including making the intention of the code clear to the user.
它在功能上等同于您已经对链接的include所做的事情,但是我认为它具有许多好处,包括使用户清楚代码的意图。
The includes 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);
}
It's just another way of doing the same thing, but I like the clarity it adds to the code. 这只是做同一件事的另一种方式,但是我喜欢它为代码增加的清晰度。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.