我正在使用 Entity Framework Core 使用以下代碼從資料庫中查詢資料:
CamicDbContext context = new CamicDbContext();
public override object Read(DataManagerRequest dm, string key = null)
{
IQueryable<Country> query = context.Set<Country>();
query = query.Where(x => x.IsDeleted == false);
query = query.Where(x => x.Code == "PT");
int count = query.Cast<Country>().Count();
return dm.RequiresCounts ? new DataResult() { Result = query, Count = count } : (object)query;
}
當query變數宣告,它似乎越來越所有專案在表(影像1),這似乎是錯誤的,因為它是低效的更大的物體; 因此,我想在不獲取資料的情況下初始化變數,構建查詢,然后僅在查詢到達時執行查詢,return query以便服務器僅查詢并回傳與過濾器匹配的專案。
我嘗試了多種解決方案。這個 -
uj5u.com熱心網友回復:
當宣告查詢變數時,它似乎正在獲取表中的所有專案(圖 1),
不是
我錯過了使用延遲執行的東西嗎?
你是
這是我打開登錄后測驗應用程式的螢屏截圖。在測驗應用程式的代碼中,我創建了一個背景關系,構建了一個查詢,然后運行它......事實上有幾次......

x是背景關系。如果我打開除錯器并展開除錯器工具提示中的“訂單”“表”,底部會顯示一條訊息,指出查看結果將列舉可列舉項。如果我列舉,那么將執行 SQL:

沒有關于此的任何子句 - 我們正在列舉Orders代表整個表的任何子句,因此 SQL 運行是有效的SELECT * FROM Orders。我的訂單測驗表中沒有任何資料,這就是為什么我們在列舉完成后看到“沒有結果”,但如果有 1000 個訂單,除錯器工具提示中將有 1000 個專案
下一行代碼運行一個 LINQ Where:

這實際上并沒有執行任何SQL,但是它提供了一個EF可以翻譯成SQL的子句,所以如果你查看回傳的DebugView屬性,你可以看到EF在運行時將形成的SQL ( ) .IQueryableWhere...WHERE Ref = ''
列舉可查詢的實際上會運行 SQL。呼吁結果在除錯器中查看將一一列舉,因為會做這樣的事情ToArray,ToList,ToDictionary(內部都羅列),甚至一個普通的舊foreach您可查詢等。每當有列舉時,它就會觸發 SQL 的運行。
如果您使用諸如 First、Count、Single 之類的東西,那么這些也會觸發 SQL 查詢的執行;他們不列舉整個集合,他們修改正在運行的 SQL 但他們確實導致執行..
..這讓我想到了評論中提出的觀點。
我撰寫的代碼使 EF 能夠使用 WHERE 子句形成查詢,但隨后它要求 DB 執行兩次:一次獲取 Count(呼叫.Count導致 a SELECT COUNT(*) ... WHERE ..),然后再次獲取實際資料項(呼叫ToList執行a SELECT 列 ... WHERE ...`):

鑒于您必須在列舉期間檢索例如 100 個專案,因此檢索所有專案然后獲取它們的本地計數會更有意義;如果您已將它們藏在串列中,則該串列將跟蹤計數
請記住,當您使用 EF 的集合并且您還沒有做任何事情來列舉它們時,可查詢的您正在傳遞和呼叫操作本質上代表一個 SQL(或部分構建的 SQL),并且每次您對它做一些傳遞資料的事情,它會運行 SQL
uj5u.com熱心網友回復:
LINQ 可以通過以下兩種方式之一執行:立即或延遲。立即執行意味著讀取資料源并在代碼中宣告查詢的點執行操作。所有回傳單個不可列舉結果的標準查詢運算子都會立即執行,而延遲執行基本上意味著該操作不在代碼中宣告查詢的位置執行。只有在列舉查詢變數時才執行該操作。
擴展和查看IQueryablewhen 除錯將作為即時查詢執行,從而將該查詢帶入記憶體。在非除錯環境中,這不會發生,查詢將作為延遲查詢執行,這意味著一旦Count()呼叫該方法,它將實際執行
有關按執行方式對標準查詢運算子進行分類的更多資訊,請參見此處 - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/classification-of-standard-query-運營商的執行方式
uj5u.com熱心網友回復:
見https://weblogs.asp.net/zeeshanhirani/using-asqueryable-with-linq-to-objects-and-linq-to-sql
1.當您使用 AsQueryable 運算子時,允許進一步的轉換:過濾、排序或聚合 2.附加的 lambda 陳述句被轉換為運算式樹。我使用 lambda 函式來說明運算式過濾器。3.如果您在未實作 IQueryable 且僅實作 IEnumerable< T > 的查詢上使用 AsQueryable 運算子,則您對查詢應用的任何轉換都將自動回退到 IEnumerable 規范。4. IQueryable if 延遲到呼叫 foreach 并計算運算式樹
Product[] products =
{
new Product {ProductId=1, Name="Kayak",Category="Watersports",Price=275m, Company=new Company{ CompanyName="Abc Corp",States=new String[]{"Ut","Id" } } },
new Product {ProductId=2, Name="Lifejacket", Category="Watersports",Price=48.95m, Company=new Company{ CompanyName="X Corp",States=new String[]{"Ca","Az" } }},
new Product {ProductId=3, Name="Soccer Ball", Category="Soccer",Price=19.50m, Company=new Company{ CompanyName="Y Corp",States=new String[]{"Tx","Wa" } }},
new Product {ProductId=4, Name="Corner Flag", Category="Soccer",Price=34.95m, Company=new Company{ CompanyName="Z Corp",States=new String[]{"Co","Wy" } }}
};
Transaction[] transactions =
{
new Transaction{ Name ="Bob Smith", ProductId=1, Cost=10.95M, Quantity=10},
new Transaction{ Name ="Dan Brown", ProductId=3, Cost=5.99M, Quantity=1}
};
IQueryable<Product> query = products.AsQueryable<Product>();
Expression<Func<Product, bool>> filter = x => x.Price > 100;
query = query.Where(filter);
int count = query.Cast<Product>().Count();
var result = query.Join(transactions,
product => new { product.ProductId },
transaction => new { transaction.ProductId },
(product, transaction) =>
new
{
CustomerName = transaction.Name,
ProductName = product.Name,
CompanyName = product.Company.CompanyName,
Price = product.Price
}) ;
foreach (var item in result)
{
_output.WriteLine($"Count: {count} Company: {item.CompanyName} Customer: {item.CustomerName} Product : {item.ProductName} Price : {String.Format("{0:C}", item.Price)}");
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/401353.html
