問題
我有一個加載本地資料檔案的客戶端應用程式。該資料檔案為每個專案指定Type和Version。
從這個檔案中,我編譯了一個Type和Version對的串列。
var typeVersionSets = datafile.Select(item => new { Type = item.TypeId, Version = item.VersionId }).Distinct();
注意:不止這兩個欄位,但為了簡單起見,我只表示這兩個。
我還有一個在云中運行的 SQL Server。我需要從滿足值對的表中獲取所有記錄(因此列值必須同時匹配)。
我撰寫了這個無法由 EF Core 運行的簡單查詢:
List<MyTableRow> MyResult = await dbContext.MyTable
.Where(dbItem => typeVersionSets.Contains(new { Type = dbItem.TypeId, Version = dbItem.VersionId }))
.ToListAsync();
我收到以下運行時錯誤:
發生一個或多個錯誤。(無法翻譯 LINQ 運算式 'DbSet().Where(p => __MyTableRowTypeVersions_2.Contains(new { Type = p.TypeId, Version = p.VersionId }))'。要么重寫查詢形式,已翻譯,或通過插入對“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的呼叫顯式切換到客戶端評估。有關詳細資訊,請參閱https://go.microsoft.com/fwlink/?linkid=2101038 .)
TLDR 一些細節
這MyTable是巨大的,我不能每次都下載它并評估客戶端上的 LINQ 運算式。
數量typeVersionSets相當少(比如說 10 套)。
當然,我可以typeVersionSets像這樣回圈:
List<MyTableRow> MyResult = new List<MyTableRow>();
foreach (var set in typeVersionSets)
{
MyResult.AddRange(
await dbContext.MyTable
.Where(pp => pp.TypeId == set.Type && pp.VersionId == set.Version)
.ToListAsync()
);
}
但是,這將需要 10 次資料庫呼叫。
每個用戶和許多用戶將多次執行此代碼。
是否有更有效的解決方案可以導致每個事件呼叫 1 個資料庫,而不會將大量不必要的資料傳輸到客戶端(或服務器)。
一些附加說明
我用:
- .NET(核心)5.0
- 物體框架核心版本 5.0.9。
萬一這很重要,我不能遷移到 EF Core 6,因為這需要遷移到 .NET(核心)6.0,這會引發很多超出我范圍的問題。
uj5u.com熱心網友回復:
我傾向于建立一個動態Expression<Func<MyTableRow, bool>>來表示過濾器。
var p = Expression.Parameter(typeof(MyTableRow), "dbItem");
var parts = new List<Expression>();
foreach (var set in typeVersionSets)
{
var typeIdValue = Expression.Property(p, nameof(MyTableRow.TypeId));
var typeIdTarget = Expression.Constant(set.Type);
var typeIdTest = Expression.Equal(typeIdValue, typeIdTarget);
var versionIdValue = Expression.Property(p, nameof(MyTableRow.VersionId));
var versionIdTarget = Expression.Constant(set.Version);
var versionIdTest = Expression.Equal(versionIdValue, versionIdTarget);
var part = Expression.AndAlso(typeIdTest, versionIdTest);
parts.Add(part);
}
var body = parts.Aggregate(Expression.OrElse);
var filter = Expression.Lambda<Func<MyTableRow, bool>>(body, p);
List<MyTableRow> MyResult = await dbContext.MyTable
.Where(filter)
.ToListAsync()
運算式樹 (C#) | 微軟檔案
uj5u.com熱心網友回復:
您可以使用此擴展程式:
dbContext.MyTable
.FilterByItems(typeVersionSets, (pp, set) => pp.TypeId == set.Type && pp.VersionId == set.Version, true)
.ToListAsync();
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/414964.html
標籤:
上一篇:找不到與ActionContext錯誤關聯的IRouter
下一篇:為什么物體框架不在這里拋出例外?
