2015-10-24 21 views
0

我目前正在爲我的ASP.VNext應用程序實現repository pattern。我希望這些方法是異步和可過濾的。所以我設計了下面的接口方法:爲什麼在EF7中爲謂詞使用參數時無法使用ToListAsync()?

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();

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

public async Task<MyEntity> GetOneAsync(Func<MyEntity,bool> predicate) 
{ 
    //save to a local variable to prevent calling a disposed DbContext 
    var entities = await Task.Run(() => ctx.Contracts.Where(predicate).FirstOrDefault()); 
    return entities; 
} 

我有一個關於這兩個問題:

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

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

+0

關於1,您可以發佈完整的代碼和編譯器消息。可能是一個微不足道的問題。 – usr

回答

1

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>不會有相同的行爲。這將從db服務器加載行而不進行任何過濾,並且在db客戶機上評估每一個行,直到找到匹配。這會增加很多開銷。

相關問題