C# 过滤后的EF核心包括:;Include中使用的Lambda表达式无效";

C# 过滤后的EF核心包括:;Include中使用的Lambda表达式无效";,c#,linq,.net-core,entity-framework-core,ef-core-5.0,C#,Linq,.net Core,Entity Framework Core,Ef Core 5.0,我正在尝试使用一个非常基本的功能,使用EF Core 5.0.0的新“过滤包含”功能 但我遇到了一个问题。它给出了以下错误: System.InvalidOperationException: Lambda expression used inside Include is not valid. 下面是导致它的代码片段。根据文件,我相信我的逻辑是正确的。我不知道为什么会发生这种情况。我有什么遗漏吗? List<Vendor> vendors = context.Vendors

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

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

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();
List vendors=context.vendors
.包括(v=>v.Items.其中(i=>i.Rating>1)
.ToList();



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

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

以一对多关系中的学生为例:每个学校都有零名或多名学生,每个学生只上一所学校,即外键SchoolId所指的学校

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

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

我在这里使用自动类型。如果您确实需要供应商:

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,甚至可能只是一个字典。这使得对用户进行单元测试更加容易


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

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

以一对多关系中的学生为例:每个学校都有零名或多名学生,每个学生只上一所学校,即外键SchoolId所指的学校

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

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

我在这里使用自动类型。如果您确实需要供应商:

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,甚至可能只是一个字典。这使得对用户进行单元测试更加容易


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

我知道这可能只是粘贴了错误的代码,但您是否在Where:
之后缺少“')。包括(v=>v.Items.Where(I=>I.Rating>1))
。如果像这样离开(不要说它不会编译),它将调用toList()内部包含可能引发此类异常的内容。您是否可以共享
供应商
项目
类。我很确定您使用的是较旧版本的EF core。这应该在当前的5.0.0预览中起作用。我知道这可能只是粘贴了错误的代码,但您是否缺少“'),在Where之后:
。Include(v=>v.Items.Where(i=>i.Rating>1))
。如果像这样(不提它不会编译),它会在内部调用toList(),包括可能引发此类异常的内容。您可以共享
供应商
项目
类。我很确定您使用的是较旧版本的EF core。这应该在当前的5.0.0预览中起作用。