2010-02-01 57 views
1

我一直在解決使用閉包時使用LINQ to Entities的問題。LINQ to Entities - 支持閉包(Lambdas)?

顯然,L2E不支持關閉。含義:

var users = from user in UserRepository.FindAll() 
      select new UserDTO 
      { 
       UserId = user.UserId, 
       Tickets = from ticket in TicketRepository.FindAll() 
         where ticket.User == user 
         select new TicketDTO 
         { 
          TicketId = ticket.TicketId 
         } 
      }; 

(注意:「去哪兒」 -clause是哪裏出了問題存在,我不允許,因爲它們不是EF原始類型到一個實體比較其他實體一樣的Int32唯一的東西,等的Guid ,是允許的。)

,是無效的,因爲我不能「ticket.User」比較「用戶」

這簡直是我有問題的一個例子,我意識到,我可以在比較Id,因爲這是一個原始類型,而不是閉包。

在現實中,我的情景比這更復雜,但這是我現在需要解決的情況。

我在網上找到的解決方法是使用子查詢。這樣做有效,但對我的情況來說,這不是很有效。

問:

做任何你知道:

  1. 實體框架4將支持在閉包在LINQ到實體?
  2. 這個問題比使用子查詢有更好的解決方案嗎?
  3. 您對此主題的任何其他知識將不勝感激!

回答

2

這不是與閉包直接相關的問題。問題是(可能)您正在混合實體框架實體和您的數據傳輸對象。 LINQ提供程序試圖將查詢的表達式樹轉換爲SQL語句,並失敗,因爲它無法將數據傳輸對象與實體和數據庫分開,當然也無法處理數據傳輸對象。

我建議讓分離更清潔 - 首先從數據庫中使用LINQ to Entity獲取數據,如果需要可以使用匿名類型,然後切換到LINQ to Objects以從所檢索的數據構建數據傳輸對象,並且都應該沒事的。像下面這樣。 (只是要注意的 - 我(安全)假設庫返回IQueryable<T> S(否則整個東西不應該在所有的工作)。)

var result = UserRepository 
     .FindAll() 
     .Select(user => new 
     { 
      UserId = user.UserId, 
      TicketIds = TicketRepository 
          .FindAll() 
          .Where(ticket => ticket.User.UserId == user.UserId) 
          .Select(ticket => ticket.TicketId) 
     }); 

轉化這個查詢結果到數據傳輸對象現在是直線前進。請注意,用戶通過ID進行比較,因爲實體框架確實(尚未)支持通過引用進行比較。

+0

這只是錯誤的。 L2E完全可以實現非實體POCO,即使在v1中也是如此。請參閱http://blogs.teamb。com/craigstuntz/2009/12/31/38500 /就此而言,L2S也可以做到這一點。 – 2010-02-01 22:15:55

+0

我不想說實體框架不能投影到POCO上,但它不能處理任意位置的POCO。但再看一遍,你是對的。這個例子應該工作,因爲只使用對POCO的投影。所以問題可能是用戶實體的參考比較。 – 2010-02-02 13:21:02

+0

此示例不起作用,因爲TicketRepository .FindAll()會帶來異常「LINQ to Entities does not recognized the method」 – Tomas 2013-12-03 15:51:21

0

這裏的問題是,L2E不支持物化的對象與在數據庫中的對象引用相等,所以你需要比較基礎上的PK:

var users = from user in UserRepository.FindAll() 
      select new UserDTO 
      { 
       UserId = user.UserId, 
       Tickets = from ticket in TicketRepository.FindAll() 
         where ticket.User.UserId == user.UserId 
         select new TicketDTO 
         { 
          TicketId = ticket.TicketId 
         } 
      }; 

(假定,在這裏,該User的PK稱爲UserId。)