2013-08-06 29 views
3
var users = from u in db.UserProfiles select new UsersViewModel{ 
          UserName = u.UserName, 
          UserId = u.UserId, 
          IsDisabled = u.IsDisabled, 
          Role = Roles.GetRolesForUser(u.UserName).FirstOrDefault() 
         }; 

我想從數據庫中選擇角色並創建一個列表UsersViewModel。但是實體框架試圖在SQL方面執行投影,沒有等同於Roles.GetRolesForUser。如何執行內部LINQ到實體的方法'

什麼是替代這個或我如何在查詢內執行任何方法?

+0

您是否從數據庫獲取用戶角色? –

回答

2

最簡單的方法是從SQL獲取所需的數據,然後執行查詢後,遍歷結果並在代碼中填充函數中的其他詳細信息。

例子:

var users = (from u in db.UserProfiles select new UsersViewModel{ 
          UserName = u.UserName, 
          UserId = u.UserId, 
          IsDisabled = u.IsDisabled 
         }).ToList(); 
foreach(var user in users){ 
    user.Role = Roles.GetRolesForUser(u.UserName).FirstOrDefault(); 
} 

這裏要記住的關鍵是要分離出你在做什麼(瞭解的擔憂在你的架構分離)。首先照顧SQL,然後從其他來源擴充數據,對於您的角色提供者來說。

+0

嗯,實際上這不會執行'GetRolesForUser'在LINQ to Entities :) –

+0

@lazyberezovsky實際上,沒有什麼會。 LINQ to Entities無法執行C#代碼中的函數,因爲它必須翻譯SQL中的整個LINQ語句(或Lambda Expression)。實體框架只是一個ORM。 – CodeMonkey1313

+0

是的,這是一個正確的答案。也考慮使用'AsEnumerable' –

1

您可以強制查詢加入ToList()創建ViewModels前執行:

var users = from u in db.UserProfiles.ToList() 
    select new UsersViewModel{ 
     UserName = u.UserName, 
     UserId = u.UserId, 
     IsDisabled = u.IsDisabled, 
     Role = Roles.GetRolesForUser(u.UserName).FirstOrDefault() 
    }; 

由於CodeMonkey1313指出,我強烈建議你採用一些類型的過濾器在您的查詢:

var users = from u in db.UserProfiles 
    .Where(x => /* apply filter here */) 
    .ToList() //Force query to execute 
    select new UsersViewModel { 
     UserName = u.UserName, 
     UserId = u.UserId, 
     IsDisabled = u.IsDisabled, 
     Role = Roles.GetRolesForUser(u.UserName).FirstOrDefault() 
    }; 
+0

使用這種方法需要記住的一件事是,它可能會導致數據繁重,因爲加載整個UserProfiles表時沒有使用where子句或甚至select子句來限制返回的列可能導致大量數據回來,這是不必要的 – CodeMonkey1313

+0

我完全同意。 – Khan

+0

雖然此更新位於Linq中,但請記住編譯後的結果。它等同於.ToList()方法調用之後的foreach循環,迭代EF查詢的結果。我提到這一點,因爲Linq查詢有時可能會離開我們,並導致循環不佳的代碼 - 記住O(n)。 – CodeMonkey1313

-1

您可以將Queryable轉換爲本地執行的Enumerable:

var users = (from u in db.UserProfiles select new UsersViewModel{ 
         UserName = u.UserName, 
         UserId = u.UserId, 
         IsDisabled = u.IsDisabled)} 
        ).AsEnumerable() 
         .Select(u => new { 
         UserName = u.UserName, 
         UserId = u.UserId, 
         IsDisabled = u.IsDisabled, 
         Role = Roles.GetRolesForUser(u.UserName) }) 
         .FirstOrDefault() 
+0

需要注意兩點。 'AsEnumerable'後面缺少'()'。此外,調用'FirstOrDefault'將返回一個用戶。如果是這種情況,你應該在'AsEnumerable'之前調用'FirstOrDefault'。 – Khan

+0

考慮使用AsEnumerable()對SQL返回的數據量的影響。總是運行一個分析器來查看你的Linq創建了什麼SQL – CodeMonkey1313

+1

我添加了括號。性能問題你可能是正確的。但這可能或可能不是問題,具體取決於用戶和角色的數量。 – FrankPl