2011-07-15 39 views
2

我有一個場景,我需要在EF模型中的用戶實體的導航屬性的列上進行排序。按實體的導航屬性的字段排序 - Linq到實體

的實體: 用戶 - >國家1:n的關係

一個簡單的SQL查詢將是如下:

SELECT UserId, u.Name, c.Name 
FROM users u join countries c on u.CountryId = c.CountryId 
ORDER BY c.Name asc; 

於是我試圖複製使用LINQ上述SQL查詢實體如下 - (延遲加載啓用)

entities.users.OrderBy(field => field.country.Name).ToList(); 

但是這查詢不返回我的國家進行了名稱排序爲原生SQL查詢博夫呢。

但我繼續多一點,做了以下內容:

var enumeratedUsers = entities.users.AsEnumerable(); 
users = enumeratedUsers.OrderBy(fields => fields.country.Name).ToList(); 

但訂購enumeratedUser對象上約50個記錄約了。 7秒

有沒有更好的方式如何省略Enumerable並且不返回匿名類型?

感謝

編輯

我剛纔忘了說,EF供應商是一個MySQL的一個不是MS SQL。事實上,我只是在MS SQL中的複製數據庫上嘗試相同的查詢,並且查詢工作正常,即國家名稱的順序是正確的,所以它看起來像除了從MySQL獲取結果集並執行順序外沒有其他選擇來自可枚舉對象上的內存

+1

您沒有匿名類型。您的案例中的var關鍵字只是隱藏IEnumerable 類型,其中TEntity是您的用戶實體類型。 entities.users是一個EntityCollection(如果我理解你的EF模型的權利)已經實現了IEnumerable,所以你可以安全地使用entities.users.OrderBy(f => f.country.Name).ToList();然而,就像丹尼斯說的那樣,你必須包含所有想要的實體關聯。 –

+0

但是,不會返回不幸的縣名排序 – Ryan

+0

嘗試看看你是否能從這個鏈接得到任何東西。 http://thejoyofcode.com/Sorting_associations_in_the_Entity_Framework.aspx –

回答

0

SOLUTION

由於我曾在這兩個國家和用戶表命名的名稱是爲了執行由country.Name當MySQL連接器是產生這種輸出兩列:

SELECT `Extent1`.`Username`, `Extent1`.`Name`, `Extent1`.`Surname`, `Extent1`.`CountryId` 
FROM `users` AS `Extent1` INNER JOIN `countries` AS `Extent2` ON `Extent1`.`CountryId` = `Extent2`.`CountryId` 
ORDER BY `Name` ASC 
因此

這將導致在users.Name名稱國家名稱。名稱

但是,MySQL有rele ase版本6.4.3 .NET連接器已解決了其中一個問題其中之一是:

我們還包括一些與我們的實體框架提供者相關的SQL生成改進。 來源:http://forums.mysql.com/read.php?3,425992

感謝您對您的所有投入。我試圖儘可能地澄清,以幫助其他可能遇到我同樣問題的人。

0

您是否嘗試過使用Include

entities.users.Include["country"].OrderBy(field => field.country.Name).ToList(); 
+0

我在對象上下文中啓用了lazyloading ...這意味着我可以省略Include,對吧? – Ryan

+0

剛剛測試過...事實上,它返回的結果集與沒有包含(國家名稱未排序)相同 – Ryan

5
var enumeratedUsers = entities.users.AsEnumerable(); 
users = enumeratedUsers.OrderBy(fields => fields.country.Name).ToList(); 

這是LINQ到對象不LINQ到實體。

以上Order By子句將調用Enumerable

即訂貨會在內存中完成定義OrderBy。因此,它需要很長一段時間

編輯

它看起來像一個MySQL相關的問題

你可以試試這樣的事情。

 var users = from user in entities.users 
          join country in entities.Country on user.CountryId equals country.Id 
          orderby country.Name 
          select user; 
+0

是否有任何其他方式直接對數據庫而不是.NET對象執行調用? – Ryan

+0

@瑞恩是的。不要使用'AsEnumerable'。只需添加'orderBy',EF就會自動生成表格連接並按您的導航屬性排序 – Eranga

+0

我剛剛編輯了我的問題...做你說的只是不起作用:( – Ryan

2

entities.users.OrderBy(字段=> field.country.Name).ToList();

但是這個查詢不會返回我的國家按照其名稱排序,因爲上面的SQL查詢是原生的 。

是的,它不會返回Countries但只有Users按國家的名稱排序。 執行此查詢時,以下SQL將發送到數據庫。

SELECT u.* 
FROM users u join countries c on u.CountryId = c.CountryId 
ORDER BY c.Name asc; 

正如您所看到的,結果不包括countries的任何字段。正如你所提到的延遲加載,需要時通過它加載countires。目前,countries按照您通過延遲加載調用它的順序進行排序。您可以通過實體集的Local屬性訪問countries

這一點告訴你,如果你想通過usercountry的名稱排序,也countires由名稱排序,你需要急切地加載作爲@Dennis提到的一樣:

entities.users.Include["country"].OrderBy(field => field.country.Name).ToList(); 

這被轉換爲下面的sql。

SELECT u.*, c.* 
FROM users u join countries c on u.CountryId = c.CountryId 
ORDER BY c.Name asc;