2016-04-09 97 views
0

我有一個EF 6項目庫模式的方法。C# - IQueryable ToList異步 - EF6

private readonly DbContext _ctx = new SomeDbContext(); 

public IQueryable<TEntity> GetAll(bool noTracking = false) 
{ 
    return !noTracking ? _ctx.Set<TEntity>() : _ctx.Set<TEntity>().AsNoTracking(); 
} 

在我的其他項目,這是業務相關的,不會有任何EntityFramework.dll參考,它只是訪問該存儲庫的項目,我做了我自己的ToListAsync擴展方法。

它採用T類型的對象的IQueryable的從存儲庫返回並異步將其轉化爲T的名單

public static async Task<IList<T>> ToListAsync<T>(this IQueryable<T> query) 
{ 
    return await new Task<IList<T>>(query.ToList); 
} 

用法:

await GetAll(true).Where(<some predicate>).ToListAsync(); 

的事情是,它只是不工作。當debbuger命中擴展方法並嘗試傳遞它時,它只是停止調試,沒有錯誤,沒有例外,它只是完全停止應用程序。

我試着改變Task的創建方式,但沒有進展。

這是怎麼發生的?

謝謝。

UPDATE

Altough我已經改變了擴展方法,它顯然奏效,一個奇怪的現象仍然存在。

擴展方法只在斷點或不調用異步時執行,如果讓它自由運行,調試器/應用程序退出,它不執行進一步的代碼。

作品:

var x = repo.GetAll(true).ToListAsync().Result; 

不工作(應用程序只是退出)

var x = await repo.GetAll(true).ToListAsync(); 

更新2

所有這些測試都是在一個控制檯應用程序正在舉行,所以有必要以wait作爲異步方法,否則會退出。

MethodX().Wait(); 
+0

你爲什麼不在存儲庫中使用EF的異步方法? –

+0

我將不得不將庫方法的返回類型從'IQueryable '更改爲'任務>'。在我的業務層,我希望能夠靈活地選擇何時在列表中轉換查詢,而不是總是返回列表。有時我只需要IQueryable。但我不知道什麼需要更多時間:查詢數據庫或在List中實現結果。 – MurariAlex

回答

1

您創建的任務未啓動。你需要先調用Start()。

+0

我已經把那行改成了'return await Task.Run(()=> query.ToList());'。 – MurariAlex

0

嗯,我已經改變了擴展方法了一下。

return await Task.Run(() => query.ToList()); 

顯然它反正現在的工作,但我幾乎可以肯定,我已經試過了......

感謝。

+0

你真的不想在那裏使用'Task.Run'。你認爲這會給'ToList'帶來什麼好處? –

+0

數據庫中實體的實現(IQueryable - > ToList)可能會阻塞UI線程,如果不運行'async'。它需要在一個單獨的線程中運行。 AFAIK這是一個沉重的操作。 – MurariAlex

+0

在這種情況下,我建議您採用EF依賴關係並使用真正的異步方法,或者將這些方法公開爲同步並讓*調用*代碼使用'Task.Run'。就目前而言,它們是「假異步」 - 即具有僅在線程池中運行同步代碼的異步簽名的方法。我有一個關於這個主題的[短博客系列](http://blog.stephencleary.com/2013/10/taskrun-etiquette-and-proper-usage.html)。 –