亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Entity Framework Core LINQ 麻煩創建(選擇案例存在)查詢

Entity Framework Core LINQ 麻煩創建(選擇案例存在)查詢

C#
慕碼人2483693 2022-06-12 10:32:57
我試圖用一個額外的列列出所有項目,描述它是否由當前用戶擁有。所以我正在尋找一個生成類似于以下 SQL 的 Linq 查詢:SELECT *,   CASE WHEN     EXISTS (       SELECT NULL FROM OwnedItems       WHERE OwnedItems.UserId = @UserId AND OwnedItems.ItemId = Items.Id   )   THEN 'true'   ELSE 'false'   END AS OwnedFROM Items;根據互聯網以及成功的 LinqPad 實驗,此代碼應該可以工作。from item in Itemsselect new{   Owned = OwnedItems.Any(own => own.UserId == userId && own.ItemId == item.Id),   Item = item}在 LinqPad 中,此代碼生成與我想要的完全相同的 SQL。但在我的項目中,它做了一些完全不同的事情。我的代碼是使用 Entity Framework Core 2.1 的 .Net Core 2.1 項目。由于它是一個核心項目,因此我無法在 LinqPad 中直接對其進行測試,因為它尚不受支持。在我的項目中,此代碼會生成一個未過濾的 SELECT 語句來查詢每個項目,然后為每個項目單獨查詢以檢查它是否存在于 OwnedItems 表中。像這樣:此查詢的 1 個實例運行:Executed DbCommand (68ms) [Parameters=[], CommandType='Text', CommandTimeout='30']  SELECT *  FROM [Items] AS [item]接下來是數百個這樣的查詢,需要幾秒鐘才能運行: Executed DbCommand (32ms) [Parameters=[@__userId_0='?' (DbType = Int32), @_outer_Id='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']  SELECT CASE      WHEN EXISTS (          SELECT 1          FROM [OwnedItems] AS [ownedItems]          WHERE ([ownedItems].[UserId] = @__userId_0) AND ([ownedItems].[ItemId] = @_outer_Id))      THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)  END一些進一步的信息,也許它會有所幫助:如果我使用同一行作為 where 子句的一部分,它會完美運行。var q = from item in Items    where OwnedItems.Any(o => o.UserId == userId && o.ItemId == item.Id)    select item;上面的 linq 產生了這個漂亮的 sql:SELECT *  FROM [Items] AS [item]  WHERE EXISTS (      SELECT 1      FROM [OwnedItems] AS [o]      WHERE ([o].[UserId] = @__userId_0) AND ([o].[ItemId] = [item].[Id]))筆記:上面的代碼是手動修改的,所以可能有錯別字。請無視他們。我知道這個特定的查詢可以使用左連接和檢查空值來完成,但我的實際查詢更復雜,我需要(嵌套)存在子句。
查看完整描述

2 回答

?
喵喔喔

TA貢獻1735條經驗 獲得超5個贊

您可能需要為查詢中的“OwnedItems”導航屬性啟用即時加載: https ://docs.microsoft.com/en-us/ef/core/querying/related-data#eager-loading


如果我應該舉個例子,請發布您的完整 linq 查詢。


更新 1


似乎子查詢在 EF Core 中有 N+1 個問題,它可能會在版本 3 中修復。


參考:https ://github.com/aspnet/EntityFrameworkCore/issues/10001


更新 2


如果您不需要完全實現“項目”,您應該能夠做這樣的事情,您可以創建一個匿名對象,而不是應該將 EF “欺騙”成您想要的:


from item in Items

select new

{

   Owned = OwnedItems.Any(own => own.UserId == userId && own.ItemId == item.Id),

   Item = new { Id = item.Id, Name = item.Name }

}

參考:https ://github.com/aspnet/EntityFrameworkCore/issues/11186


查看完整回答
反對 回復 2022-06-12
?
萬千封印

TA貢獻1891條經驗 獲得超3個贊

您需要告訴 EF 加載相關數據,在本例中為OwnedItems表。

解決此問題的一種方法是包含相關表。如果有鏈接表的外鍵,則可以像這樣輕松完成:

var dataWithRelatedData = db_context.Items.Include(x => x.OwnedItems).Select ...

避免大量往返數據庫的另一種方法是將兩個數據集加載到單獨的查詢中,然后將它們合并到內存中。因此,您將首先對Items進行查詢,然后將數據返回到OwnedItems的另一個查詢,最后將它們合并到一個對象列表中。這只會對數據庫進行 2 次調用,從而提高性能。


查看完整回答
反對 回復 2022-06-12
  • 2 回答
  • 0 關注
  • 126 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號