簡體   English   中英

將 EF Core 查詢從 2.2 轉換為 3.0 - async await

[英]Converting EF Core queries from 2.2 to 3.0 - async await

在 EF Core 2.2 中,我有:

      var data = await _ArticleTranslationRepository.DbSet
        .Include(arttrans => arttrans.Article)
        .ThenInclude(art => art.Category)
        .Where(trans => trans.Article != null && trans.Article.Category != null && trans.Article.Category.Id == categoryId.Value)
        .GroupBy(trans => trans.ArticleId)
        .Select(g => new { ArticleId = g.Key, TransInPreferredLang = g.OrderByDescending(trans => trans.LanguageId == lang).ThenByDescending(trans => trans.LanguageId == defaultSiteLanguage).ThenBy(trans => trans.LanguageId).FirstOrDefault() })
        .Select(at => at.TransInPreferredLang)
        .OrderBy(at => at.Article.SortIndex)
        .ToListAsync();

現在使用 EF Core 3.0 我必須寫:

      var data = _ArticleTranslationRepository.DbSet
  .Include(arttrans => arttrans.Article)
  .ThenInclude(art => art.Category)
  .Where(trans => trans.Article != null && trans.Article.Category != null && trans.Article.Category.Id == categoryId.Value)
    .AsEnumerable() // client side groupby is not supported (.net core 3.0 (18 nov. 2019)
  .GroupBy(trans => trans.ArticleId)
  .Select(g => new { ArticleId = g.Key, TransInPreferredLang = g.OrderByDescending(trans => trans.LanguageId == lang).ThenByDescending(trans => trans.LanguageId == defaultSiteLanguage).ThenBy(trans => trans.LanguageId).FirstOrDefault() })
  .Select(at => at.TransInPreferredLang)
  .OrderBy(at => at.Article.SortIndex)
  .ToList();

我的 asp.net 核心 mvc 操作方法是異步的( public virtual async Task<ICollection<…>>… )因為我使用了 .AsEnumerable 來強制客戶端評估,所以我還必須將.ToListAsync()更改為.ToList()並刪除await運算符。

查詢正在運行但會產生警告: This async method lacs 'await' operators and will run synchronously. Consider using the 'await operator …. This async method lacs 'await' operators and will run synchronously. Consider using the 'await operator ….

如何重寫此 EF Core 3.0 查詢以使其使用異步/等待。 我不知道如何在單個查詢/linq 表達式中包含AsAsyncEnumerable()

(我知道我可以將它拆分為“服務器”部分和“客戶端”部分,但我希望像以前在 EF Core 2.2 中那樣在單個異步linq 表達式中看到它。)

這個想法似乎是將AsAsyncEnumerable()System.Linq.Async IEnumerable<T>結合起來,它提供了等效的IAsyncEnumerable<T>擴展方法。

因此,如果您安裝(或 package 參考)(或 package 參考),在 .GroupBy 之前插入.GroupBy .AsAsyncEnumerable() ,則有問題的原始查詢應該可以工作。

盡管 EF Core 3.0 DbSet<T> class 存在一個煩人的問題。 由於它同時實現了IQueryable<T>IAsyncEnumerable<T>接口,並且它們都不是“更好”(更接近)的匹配,因此在DbSet<T>上使用標准 LINQ 運算符的許多查詢將在編譯時使用CS0121 (模糊調用) 並且需要添加.AsQueryable() 使用 EF Core 特定擴展(如Include / ThenInclude將起作用,因為它們已經解析為IQueryable<T>

正如一些人在評論中提到的,可以使用(await [serverPart...].ToListAsync())[clientPart...]消除System.Linq.Async和相關的編譯時方法歧義的需要,但它通過創建不必要的內存列表,與在同步場景中使用ToList()而不是AsEnumerable()具有相同的缺點。


當然,最好的辦法是通過找到等效但完全可翻譯的 LINQ 結構來完全避免客戶評估。 目前使用GroupBy很難,有時甚至是不可能的。 即使有可能,它也需要通過消除GroupBy來重寫先前的查詢。 例如,不是從ArticleTranslation開始查詢並按ArticleId分組,您可以從Article開始查詢並將Translations集合導航屬性與支持的OrderByDescending()...FirstOrDefault()一起使用。 對每個失敗的查詢重復該過程。 這樣做的好處是,現在您的查詢將按照最初應有的方式執行服務器端。

我在 do.net core 5.0 和 6.0 上遇到了同樣的問題,我是這樣解決的:

安裝 nuget package System.Linq.Async 取決於你的.net 版本https://www.nuget.org/packages/System.Linq.Async

然后在您的查詢中,您將能夠添加 the.ToAsyncEnumerable()

這是一個例子:

        public async Task<IEnumerable<ProductTableView>> GetProduct(Pagination pagination, string identifier)
    {

        var ListProductsTable = await _context.ModelView
                                       .FromSqlRaw("GetProductByIdentifier {0}", identifier)
                                       .ToAsyncEnumerable()
                                       .Select(a => new ProductTableView
                                       {
                                           ID = a.ID,
                                           Guid = a.Guid,
                                           Guid_Product_Category = a.Guid_Product_Category,
                                           Guid_Currency = a.Guid_Currency,
                                           NameProduct = a.NameProduct,
                                       }).ToListAsync();

        return ListProductsTable;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM