為什麼在EF7中為謂詞使用參數時我不能使用ToListAsync()?

asp.net-core c# entity-framework-core

我目前正在為我的ASP.VNext應用程序實現存儲庫模式 。我希望這些方法是異步和可過濾的。所以我設計了以下接口方法:

Task<TEntity> GetOneAsync(Func<TEntity,bool> predicate);

並希望像這樣實現它(使用私有DbContext實例ctx ):

public async Task<MyEntity> GetOneAsync(Func<MyEntity,bool> predicate) 
{
    // compiler error
    return await ctx.MyEntities.Where(predicate).FirstOrDefaultAsync();
}

但是,我只能在硬編碼謂詞時使用FirstOrDefaultAsync()

return await ctx.MyEntites.Where(e => e.Id == 1).FirstOrDefaultAsync();

傳遞謂詞時我只得到沒有async選項的FirstOrDefault() ,所以為了使我的方法異步我必須寫

public async Task<MyEntity> GetOneAsync(Func<MyEntity,bool> predicate) 
{
    // compiler error
    return await ctx.MyEntities.Where(predicate).FirstOrDefaultAsync();
}

我有兩個問題:

  1. 為什麼在傳遞謂詞時無法訪問FirstOrDefaultAsync()方法?

  2. 我的解決方案是否使用await Task.Run(synchronousMethod)實現與調用FirstOrDefaultAsync()相同的行為?

一般承認的答案

FirstOrDefaultAsync被定義為IQueryable<T>的擴展方法。

ctx.MyEntities.Where(e => e.Id == 1)返回IQueryable<MyEntity>

ctx.MyEntities.Where(predicate)返回IEnumerable<MyEntity> ,因為你正在調用Enumerable.Where擴展方法,而不是Queryable.Where

要使其工作,請將predicateFunc<MyEntity, bool>更改為Expression<Func<MyEntity, bool>> 。這意味著predicate不再僅僅是一個提供所需結果的函數,而是一個對該函數的描述,然後實體框架可以轉換為SQL。

不,在任務中使用Func<MyEntity, bool>將不會有相同的行為。這將從數據庫服務器加載行而不進行任何過濾,並在數據庫客戶端評估每個行,直到找到匹配項。這會增加很多開銷。




許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因