1

我正在尝试使用带有 EF Core 5.0.0 的新“过滤包含”功能来使用一个非常基本的功能,

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

但我遇到了一个问题。它给出了以下错误:

System.InvalidOperationException: Lambda expression used inside Include is not valid.

这是导致它的代码片段。根据文档,我相信我的逻辑是正确的。我不确定为什么会这样。有什么我想念的吗?

List<Vendor> vendors = context.Vendors
                .Include(v => v.Items.Where( i => i.Rating > 1)
                .ToList();



供应商是项目的父项。这是一个非常基本的设置。一对(供应商)对多(项目)关系。

4

1 回答 1

0

使用 Select 而不是 Include 通常更有效。使用 Select 您可以选择您计划使用的属性。Include 将传输完整的项目,包括您不会使用的属性。

考虑一个具有直接一对多关系的学生的学校:每个学校有零个或多个学生,每个学生恰好就读一所学校,即外键 SchoolId 所指的学校。

假设您要查询学校 [10] 及其 2000 名学生。每个 Student of School [10] 的外键 SchoolId 的值等于 10。如果您使用 Include,您将传输此值大约 2000 次,而您已经知道该值。多么浪费处理能力。

查询数据时,始终使用 Select 并仅选择您实际计划使用的属性。仅当您计划修改包含的数据时才使用 Include。

var result = context.Vendors.Select(vendor => new
{
     // Select only the Vendor properties that you intend to use:
     Id = vendor.Id,
     Name = vendor.Name,
     ...

     HighRatedItems = vendor.Items.Where(item => item.Rating > 1)
         .Select(item => new
         {
              // again: select only the properties that you plan to use
              Id = item.Id,
              ...

              // not needed, you know the value:
              // VendorId = item.VendorId,
         })
         .ToList(),
})
.ToList();

我在这里使用自动类型。如果你真的想要供应商:

var result = context.Vendors.Select(vendor => new Vendor
{
     // Select only the Vendor properties that you intend to use:
     Id = vendor.Id,
     Name = vendor.Name,
     ...

     Items = vendor.Items.Where(item => item.Rating > 1)
         .Select(item => new Item
         {
              // again only the items that you plan to use.
              Id = item.Id,
              ...            
         })
         .ToList(),
});

请注意,某些属性将没有正确的值。这可能会让您的方法的用户感到困惑。但话又说回来:他们知道无论如何他们都不会得到“供应商及其物品”,因为您不会退回他们所有的物品,所以他们已经不期待完整的供应商对象。

为了克服未完全填充返回对象的问题,请考虑实现存储库模式。将数据库中表的类型与实际返回的数据分开。

这将需要额外的类,这些类看起来与您的原始供应商和项目非常相似。然而,它的优势在于用户将确切地知道他们得到了什么。然而,好处是如果您决定更改数据库的布局,您的用户不必更改代码。此外,存储库隐藏了您正在使用数据库。它可以是 CSV 文件,也可以是 Json,甚至可能只是一个字典。这使得对用户进行单元测试变得更加容易。

您是否应该实施存储库取决于您的数据库将拥有多少用户、单元测试的重要性以及您期望数据库更改的频率。

于 2020-05-12T06:46:20.627 回答