繁体   English   中英

实体框架ObjectQuery.Include()

[英]Entity Framework ObjectQuery.Include()

我有一个对象,其中有两个对象作为属性( UserPrimaryNode ),都可能为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; }
}

我正在使用Entity Framework 6填充Item对象,并使用链式包含在其中填充PrimaryNodeUser对象。

当第一个链接的Include具有空对象时,则整个对象将返回空值,例如:

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

如果在上面的示例中i.User为null,则item变量为null。 以某种方式填充两个子对象的最佳方法是:如果一个子对象为null,则仍将填充父对象和另一个子对象?

我认为如果您在他的情况下使用Lazy loading会更好。 只需将UserPrimaryNode虚拟:

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; }
}

然后:

var db = new MyContext();
var item = db.Items.FirstOrDefault(i => i.ItemId == id);

我认为您的问题不是由于Include通话引起的。 根据文档

如果存在这样的方法,则此扩展方法将调用IQueryable源对象的Include(String)方法。 如果源IQueryable没有匹配方法,则此方法不执行任何操作

换句话说,将被翻译为:

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

我的问题是,您确定您有一个ID与数据库中UsersPrimaryNodes表中的现有行正确相关的Item吗? 当您在最后调用Include方法将转换为联接时,因此,如果关系的FK与该引用的PK不匹配,则查询不应返回期望的结果。

无论如何,如果您想尝试另一个变体来加载相关属性,则可以使用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();

正如其他人所提到的,我认为您的问题并非归因于Includes。 但是,我认为以下方法有价值。 它在功能上等同于您已经对链接的include所做的事情,但是我认为它具有许多好处,包括使用户清楚代码的意图。

包括可以放在扩展方法中:

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);
        }
    }
}

然后,您可以按以下方式使用扩展名:

using (var db = new MyContext())
{
    var itemQuery = db.Items.IncludeUser();

    itemQuery = itemQuery.IncludePrimaryNode();

    var item = itemQuery.FirstOrDefault(i => i.Id == 1);
}

这只是做同一件事的另一种方式,但是我喜欢它为代码增加的清晰度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM