【问题标题】:How can I fully load a recursive model on multiple levels with entity framework?如何使用实体框架在多个级别上完全加载递归模型?
【发布时间】:2020-04-22 22:52:19
【问题描述】:

编辑:这是答案Is recursive query possible in LINQ 已经回答了,肯定错过了。

我使用的是 .NET Core 2.2。

我查看了该网站上提出的多个问题,但没有一个对我有用。

我的模型看起来像这样(简化):

public class Product
{
    /// <summary>
    ///     Gets or sets the Id.
    /// </summary>
    public string Id { get; set; }

    /// <summary>
    ///     Gets or sets the code.
    /// </summary>
    public string Code { get; set; }

    /// <summary>
    ///     Gets or sets the properties.
    /// </summary>
    public List<Property> Properties { get; set; }

    /// <summary>
    ///     Gets or sets the products
    /// </summary>
    public List<Product> Products { get; set; }
}

public class Property
{
    /// <summary>
    ///     Gets or sets the Id.
    /// </summary>
    public string Id { get; set; }

    /// <summary>
    ///     Gets or sets the code
    /// </summary>
    public string Code { get; set; }
}

我正在尝试加载包含所有子产品的产品,还包括所有产品的属性。

首先,我能够递归加载所有产品,但老实说我不知道​​它为什么会起作用。

我试过这个:

var products1 = this._context.Products.Where(x => x.Code == "TEST").Include(x => x.Products);

它只会加载第一级产品的产品。

然后由于纯粹的运气/错误,我在上述那一行之前离开了这一行:

this._context.Products.ToList()

然后,第一行实际上递归地加载了所有产品......我猜不错吧?

无论如何,现在我要做的是递归加载所有产品,同时加载它们的所有属性。

我已经尝试了几件事,包括看起来很阴暗:

this._context.Products.Where(x => x.Code == "TEST").Include(x => x.Properties)
            .Include(x => x.Products).ThenInclude(x => x.Properties);

但无论我做什么,我只会加载第一级递归产品的属性。 我仍然以递归方式完全加载所有产品,但只有前 2 个级别加载了它们的属性。

所以最终我的问题是我该怎么做?作为一个额外的问题,如果回答了真正的问题,无论如何都可以回答:为什么我需要写这行:

this._context.Products.ToList()

在这一行之前:

var products1 = this._context.Products.Where(x => x.Code == "TEST").Include(x => x.Products);

递归加载产品?

编辑:请注意,我知道我可以在循环中使用多个查询(每个产品一个)递归加载所有产品/属性,但如果可能的话,我绝对希望避免这种情况。

【问题讨论】:

  • 你在哪里定义关系?
  • @IvanStoev 哦,有趣。没看到那个,我试试看。
  • @user2509192 是的,您将能够加载其他相关数据(使用Include / ThenInclude)。 “唯一”的问题是这对于返回单个/少量项目不是那么有效,因为它需要在内存中检索/处理整个表(因此还有很多不必要的相关数据)。
  • @IvanStoev 非常感谢它的工作原理!顺便说一句 WithOptional 不再存在。我们现在使用 WithOne,当 FK 可以为空时,它被视为可选,否则是的,你的答案就是答案。

标签: entity-framework linq .net-core entity-framework-core


【解决方案1】:

急切加载不会递归工作,但您可以使用延迟加载。这会影响您的性能,但您将能够迭代所有层。

参考https://docs.microsoft.com/en-us/ef/core/querying/related-data

使用延迟加载的最简单方法是安装 Microsoft.EntityFrameworkCore.Proxies 包并通过调用 UseLazyLoadingProxies 来启用它。例如:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
    .UseLazyLoadingProxies()
    .UseSqlServer(myConnectionString);

EF Core 将为任何导航属性启用延迟加载 可以被覆盖——也就是说,它必须是虚拟的并且在一个可以 继承自。

因此,将您的 Lists 转换为虚拟收藏,一切顺利。

【讨论】:

  • 问题是我的属性不能直接在应用程序中访问。我的查询结果通过帖子发送到另一个应用程序。 (作为 json)。
  • @user2509192 没关系。像JsonConvert.SerializeObject() 这样来自Newtonsoft.Json 的标准序列化程序将遍历IEnumerable 对象并将它们包含在JSON 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-28
  • 2012-06-05
  • 1970-01-01
相关资源
最近更新 更多