C# 如何使用函数where with ToListAsync()

C# 如何使用函数where with ToListAsync(),c#,.net-core,async-await,entity-framework-core,ef-core-2.1,C#,.net Core,Async Await,Entity Framework Core,Ef Core 2.1,我写了一个where函数来检查产品是否有一些功能,并找到一个价格最高的产品 我的简单模型如下所示: public class Product { public long ProductID { get; set; } [MaxLength(150)] public string Name { get; set; } public List<Functionality> Functionalities { get; set; } publi

我写了一个where函数来检查产品是否有一些功能,并找到一个价格最高的产品

我的简单模型如下所示:

 public class Product
 {
    public long ProductID { get; set; }
    [MaxLength(150)]
    public string Name { get; set; }

    public List<Functionality> Functionalities { get; set; }
    public List<Price> Prices { get; set; }
 }

 public class Functionality
 {
    public long FunctionalityID { get; set; }
    [MaxLength(150)]
    public string Name { get; set; }

    [Required]
    public long ProductID { get; set; }
    public Product Product { get; set; }
 }

 public class Price
 {
    public long PriceID { get; set; }
    public decimal Value { get; set; }

    [Required]
    public long ProductID { get; set; }
    public Product Product { get; set; }
 }
 public List<Product> GetList(ProductFiltersDto filters)
 {
    return _context.Product
        .Include(x => x.Functionality)
        .Include(x => x.Price)
        .Where(x =>
            CheckCollectionFilter(x.Functionality.Select(f => f.FunctionalityID), filters.Functionalities) &&
            CheckMaximumPrice(x.Prices , filters.MaxPrice)
         )
         .ToList();

 }
private Expression<Func<T, bool>> CheckCollectionFilter<T>(IEnumerable<T> filterCollection);

private Expression<Func<T, bool>> CheckMaximumPrice<T>(decimal? avalibleMinPrice);
公共类产品
{
公共长ProductID{get;set;}
[MaxLength(150)]
公共字符串名称{get;set;}
公共列表功能{get;set;}
公开标价{get;set;}
}
公共类功能
{
公共长函数ID{get;set;}
[MaxLength(150)]
公共字符串名称{get;set;}
[必需]
公共长ProductID{get;set;}
公共产品产品{get;set;}
}
公共类价格
{
公共长PriceID{get;set;}
公共十进制值{get;set;}
[必需]
公共长ProductID{get;set;}
公共产品产品{get;set;}
}
然后,我的同步功能可以找到正确的产品,如下所示:

 public class Product
 {
    public long ProductID { get; set; }
    [MaxLength(150)]
    public string Name { get; set; }

    public List<Functionality> Functionalities { get; set; }
    public List<Price> Prices { get; set; }
 }

 public class Functionality
 {
    public long FunctionalityID { get; set; }
    [MaxLength(150)]
    public string Name { get; set; }

    [Required]
    public long ProductID { get; set; }
    public Product Product { get; set; }
 }

 public class Price
 {
    public long PriceID { get; set; }
    public decimal Value { get; set; }

    [Required]
    public long ProductID { get; set; }
    public Product Product { get; set; }
 }
 public List<Product> GetList(ProductFiltersDto filters)
 {
    return _context.Product
        .Include(x => x.Functionality)
        .Include(x => x.Price)
        .Where(x =>
            CheckCollectionFilter(x.Functionality.Select(f => f.FunctionalityID), filters.Functionalities) &&
            CheckMaximumPrice(x.Prices , filters.MaxPrice)
         )
         .ToList();

 }
private Expression<Func<T, bool>> CheckCollectionFilter<T>(IEnumerable<T> filterCollection);

private Expression<Func<T, bool>> CheckMaximumPrice<T>(decimal? avalibleMinPrice);
public List GetList(ProductFiltersDto过滤器)
{
return\u context.Product
.Include(x=>x.Functionality)
.包括(x=>x.价格)
.其中(x=>
CheckCollectionFilter(x.Functionality.Select(f=>f.functionatyid),filters.functionaties)&&
检查MaximumPrice(x.Prices,filters.MaxPrice)
)
.ToList();
}
下面是我的where函数:

private bool CheckCollectionFilter<T>(IEnumerable<T> collection, List<T> filterCollection)
{
    if (filterCollection != null)
    {
        var result = true;
        foreach (var filterValue in filterCollection)
        {
            if (!collection.Contains(filterValue))
            {
                result = false;
                break;
            }
        }

        return result;
     }
     else
     {
         return true;
     }
}

private bool CheckMaximumPrice(List<Price> prices, decimal? avalibleMinPrice)
{
    return avalibleMinPrice.HasValue && prices.Count > 0 ? prices.Min(x => x.Value) <= avalibleMinPrice : true;
}
private bool CheckCollectionFilter(IEnumerable集合、列表过滤器集合)
{
if(filterCollection!=null)
{
var结果=真;
foreach(filterCollection中的var filterValue)
{
如果(!collection.Contains(filterValue))
{
结果=假;
打破
}
}
返回结果;
}
其他的
{
返回true;
}
}
私人bool CheckMaximumPrice(标价,十进制?有效价)
{

return avalibleMinPrice.HasValue&&prices.Count>0?prices.Min(x=>x.Value)一旦从
iQuery
移动到
IEnumerable
,EntityFramework将在数据库服务器上执行到目前为止的查询,将所有数据拉入内存,并在内存中执行其余的查询

如果要使其在数据库服务器中运行,则必须使查询保持可序列化,并使用表达式树而不是可执行代码

你需要想出这样的办法:

 public class Product
 {
    public long ProductID { get; set; }
    [MaxLength(150)]
    public string Name { get; set; }

    public List<Functionality> Functionalities { get; set; }
    public List<Price> Prices { get; set; }
 }

 public class Functionality
 {
    public long FunctionalityID { get; set; }
    [MaxLength(150)]
    public string Name { get; set; }

    [Required]
    public long ProductID { get; set; }
    public Product Product { get; set; }
 }

 public class Price
 {
    public long PriceID { get; set; }
    public decimal Value { get; set; }

    [Required]
    public long ProductID { get; set; }
    public Product Product { get; set; }
 }
 public List<Product> GetList(ProductFiltersDto filters)
 {
    return _context.Product
        .Include(x => x.Functionality)
        .Include(x => x.Price)
        .Where(x =>
            CheckCollectionFilter(x.Functionality.Select(f => f.FunctionalityID), filters.Functionalities) &&
            CheckMaximumPrice(x.Prices , filters.MaxPrice)
         )
         .ToList();

 }
private Expression<Func<T, bool>> CheckCollectionFilter<T>(IEnumerable<T> filterCollection);

private Expression<Func<T, bool>> CheckMaximumPrice<T>(decimal? avalibleMinPrice);

即使您得到要编译的代码。EF也无法将调用自定义方法的表达式转换为SQL,因此代码在运行时也会失败。@Servy您是指同步或异步版本还是两者都有?如果您说同步,这项工作很好。如果在异步版本中,我删除函数,这项工作也很好,很简单,在哪里工作时喜欢
where(x=>x.Name=“你的名字在这里”)
显然,与EF不同的是,EF core决定,每当查询无法转换为SQL时,它都会默默地将整个内容拉到内存中,并在内存中进行计算,而在这种情况下,您肯定不希望这样做。因此,您的查询只是默默地不工作,而不是实际地转换查询没错。这是正确的。EF core会在必要时悄悄地切换到客户端求值。我的理解是,
ToListSync
从数据库端求值表达式生成一个
IAsyncEnumerable
,然后将其交给客户端方法
CheckCollectionFilter
,这显然是因为
IAsync>而失败的Enumerable
未实现
IEnumerable
@Servy谢谢我会检查答案是否正确。EF核心客户端评估问题(默认启用)虽然从
IQueryable
IEnumerable
之间没有明确的移动,但人们可能甚至没有意识到存在这样的转换。相反,EF6要求转换是显式的(通过
AsEnumerable()
或类似方式)。好吧,这可能对你和我来说都很清楚,但大多数人没有意识到,当你在
IQueryable
表达式树(
)中使用自定义方法时(
),其中(x=>SomeCustomMethod(x.y)
)是在不同的上下文中执行的。顺便说一句,这只是“澄清”注释,我同意你的解决方案(UV由我提供:)我明白你的意思了,伊万。我参加工作面试,这通常是缺乏知识的。