【问题标题】:Entity Framework will not load related entity when using .Include unless the context knows about the related entity实体框架在使用 .Include 时不会加载相关实体,除非上下文知道相关实体
【发布时间】:2014-09-15 14:57:26
【问题描述】:

使用 Entity Framework 6.1.x 和启动基本 Asp.NET MVC 项目时包含的默认用户 (ApplicationUser) 模型。与该问题相关的是另外两个实体:客户和组织(都在进行中)。下面是 Customer 类。

public class Customer
{
    public Customer()
    {
    }

    public int Id { get; set; }

    public string UniqueId { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string Email { get; set; }

    public Organization Organization { get; set; }
}

无论出于何种目的,组织都可以被视为具有单个 Id 属性的最小实体。

以下代码不会在客户集合中包含组织:

var customers = this.context.Customers.Include(c => c.Organization)
    .Join(this.context.Users.Where(u => u.Id == userId), c => c.Organization.Id, u => u.Organization.Id, (c, u) => c)
    .ToList();

但是,当我将 virtual 添加到 Customer.Organization 属性时,或者如果我通过运行 this.context.Organizations.ToList() 让上下文了解有关组织的信息,它将起作用。

最后,基于this post 谈到.Include().Include() 发出后如果查询改变形状将无法工作,我编写了以下代码:

var customers = this.context.Customers
    .Join(this.context.Users.Where(u => u.Id == userId), c => c.Organization.Id, u => u.Organization.Id, (c, u) => c)
    .AsQueryable<Customer>().Include(c => c.Organization)
    .ToList();

最后一个代码 sn-p 有效,所以我想我可以使用它。

不过,它不如第一个代码漂亮,但更重要的是,我真的很想了解为什么第一个代码不起作用。是因为“查询的形状”正在改变吗?如果是这样,当我在调用查询之前让上下文了解组织时,它是如何工作的?

【问题讨论】:

    标签: c# asp.net-mvc entity-framework include


    【解决方案1】:

    延迟加载

    添加virtual 关键字(带有Configuration.ProxyCreationEnabled = true)将启用延迟加载。

    当上下文仍然存在时,任何以编程方式访问导航属性都会自动加载引用(如果尚未加载)。

    本地数据

    调用context.Organizations.ToList() 会将所有组织从数据库加载到内存(在本例中为Local data)。而且由于它是在同一个上下文中加载的,所以当本地数据更新时,所有正在跟踪的引用也将被更新。

    包括限制

    要使您的初始代码正常工作,您需要更改连接结果

    (c, u) => c
    

    (c, u) => new { Customer = c, Organization = c.Organization }
    

    customers 结果将变为包含Customer 属性的匿名类型集合。要返回Customer,您需要有额外的代码,例如。

    .ToList().Select(c => c.Customer).ToList();
    

    第一个查询看起来像。

    var customers = this.context.Customers.Include(c => c.Organization)
        .Join(this.context.Users.Where(u => u.Id == userId), c => c.Organization.Id, u => u.Organization.Id, (c, u) => new { Customer = c, Organization = c.Organization })
        .ToList().Select(c => c.Customer).ToList();
    

    你给的The article是回复this question的人写的。

    【讨论】:

    • 我明白了。我选择禁用延迟加载,所以虚拟不是一个选项。您答案的包含限制部分非常有帮助,并且确实解决了问题(尽管不再需要使用“.Include(c => c.Organization)”)。虽然它并不漂亮,但对此无能为力。
    猜你喜欢
    • 2014-10-23
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多