2017-08-27 62 views
1

在我的ASP.NET MVC網站中,用戶瀏覽書籍。他們可以選擇添加他們自己創建的列表中的每本書。外部DbContext調用期間EF DbContext的內部調用異步行爲ASP.NET MVC

當用戶瀏覽一本書時,每本書下面的所有列表都有一個下拉列表,他可以選擇添加書籍。迄今爲止所有的都很好,但是我現在想要的是,如果該書已經包含在用戶列表中的一個列表中,則該下拉列表應該知道。

這是相關視圖模型:

public class UserBookListsMinimalVM { 
    public int ListId { get; set; } 
    public string ListName { get; set; } 
    public bool BookAlreadyInList { get; set; } 
} 

這是我跑檢索項查詢:

var userBookLists = await context.vwUserBookLists 
           .Where(x => x.ListOwner == userName) 
           .Select(x => new UserBookListsMinimalVM 
           { 
            ListId = x.ListId, 
            ListName = x.ListName, 
            BookAlreadyInList = context.List_Books.Any(y => y.ListId == x.ListId && y.BookId == bookId) 
           }) 
           .OrderBy(x => x.ListName) 
           .ToListAsync(); 

vwUserBookLists是包含列表相關的信息和List_Book一個觀點是中介列表和書籍之間的表格(包含每個列表的書籍等)。

由EF生成的SQL嵌套SELECT語句,主要是爲了解釋BookAlreadyInList屬性。 (我不知道查詢是否可以簡化的,我願意接受建議)

BookAlreadyInList分配「破發」的全功能的異步過程中不調用context,看它是不是await版?

+1

您是否觀察到此代碼出現任何意外行爲?有什麼不工作?我不清楚你究竟在問什麼。對'.Any()'的調用不需要等待,因爲它不是異步的。 – David

+0

嗨@大衛 - 它工作正常(即它返回預期的結果)。我的問題是在'BookAlreadyInList'分配期間對'context'的非異步調用是否與外部'await context'異步調用衝突'。應該.Any()成爲'.AnyAsync()'? – globetrotter

+1

我不認爲有'.AnyAsync()'(儘管你可以很快測試)。實際上並不需要,因爲'.Any()'實際上並未實現數據源中的任何內容。它被轉換爲支持數據存儲的表達式樹,就像其他更多的LINQ方法一樣。只有實際物化數據的方法(比如'.ToList()')需要異步版本。 – David

回答

2

它不會破壞你的異步操作,當ToListAsync()完成這項工作時它將完成。只有一個異步操作,在此之前不會被任何異常操作破壞,無論您在查詢中做什麼,都會遵守await /異步合同。即使你試圖實現其中的一些實體,例如調用同步的ToList()(假設EF會容忍這個),這個同步調用將在後臺線程中進行。您不能在您的查詢中使用AnyAsync,因爲sql提供程序無法轉換異步操作,該操作特定於c#而不是sql server。

這就是說,更重要的是,你仍然可以問自己EF是否只向數據庫發送一個查詢,或者將你的查詢翻譯成多個數據庫調用(可能是這種情況,這取決於你使用的版本),甚至在內存中進行一些操作。要知道究竟發生了什麼,最好的方法是查看輸出窗口,看看是否可以看到生成的sql,或者在執行代碼時啓動觀察數據庫的sql profiler。 在.net核心的最新版本中,您可以配置您的dbcontext以在表達式樹無法完全轉換爲sql並且必須在內存中執行某些操作時拋出異常。如果您不這樣做,您仍會在輸出窗口中收到警告。