[英]Linq Query To Return Complex Type
我有一個非常標准的用戶和角色模型:
+-------+ +-----------+ +-------+
| Users | | UserRoles | | Roles |
+-------+ +-----------+ +-------+
| ID (P)| < | UserID (P)| | ID (P)|
| ... | | RoleID (P)| > | ... |
+-------+ +-----------+ +-------+
我使用Entitiy框架作為我的ORM,我正在嘗試構建 - 在單個Linq查詢中 - 我的ViewModel,定義如下:
public class RoleDetail {
public class RoleUser {
public int ID { get; set; }
public string Username { get; set; }
}
public int ID { get; set; }
public string Rolename { get; set; }
public bool Active { get; set; }
public IEnumerable<RoleUser> Users { get; set; }
}
我認為以下查詢應該有效:
var query = Context.Roles
.Include("Users")
.Where(r => r.ID == id)
.Select(r => new RoleDetail() {
ID = r.ID,
Rolename = r.Rolename,
Active = r.Active,
Users = r.Users
.Select(u => new RoleDetail.RoleUser() {
ID = u.ID,
Username = u.Username
})
.ToList()
})
.FirstOrDefault();
但是,這會引發以下錯誤:
LINQ to Entities無法識別方法'System.Collections.Generic.List [RolesRepository + RoleDetail + RoleUser] ToList [RoleUser](System.Collections.Generic.IEnumerable [RolesRepository + RoleDetail + RoleUser])'方法,而且這個方法不能被翻譯成商店表達。
我沒有和Linq一起工作過,所以我很確定我的查詢在某種程度上是錯誤的。 有人可以告訴我我的查詢出錯的地方,以及是否有更好的方法來實現我想要實現的目標?
先感謝您!
對linq-to-entities的經驗很少,所以這是一個黑暗中的鏡頭:
你為什么需要.ToList()?
.Select()已經返回一個IEnumerable,所以它應該沒有。
ToList()返回一個List,而不是一個IList或類似的接口,而是一個具體的c#類。 因此,我認為Linq to Entities無法將其轉換為自己的幕后語法
這有用嗎?
var query = Context.Roles
.Include("Users")
.Where(r => r.ID == id)
.Select(r => new RoleDetail() {
ID = r.ID,
Rolename = r.Rolename,
Active = r.Active,
Users = r.Users
.Select(u => new RoleDetail.RoleUser() {
ID = u.ID,
Username = u.Username
})
// .ToList()
})
.FirstOrDefault();
LINQ查詢中發送到EF LINQ提供程序的所有內容都需要是L2E可以直接轉換為SQL的表達式。 您可以手動分離EF可以翻譯的部分,以及必須在LINQ 2對象中完成的部分。
執行發生在必須實際枚舉查詢的位置,在您的情況下是FirstOrDefault
調用。 您可以通過調用IQueryable.AsEnumerable()
來強制執行查詢。 之后的任何事情都由LINQ 2對象處理,幾乎可以做任何你想做的事情。
在你的情況下,lambda表達式唯一不可翻譯的方面是對ToList
的調用,它沒有數據庫等價物,所以你根本就不能調用它; 這樣做的缺點是你的Users
屬性將設置一些任意內部類,恰好是EF的實現中IQueryable.Select
的結果。 這對您來說可能是也可能不是問題,具體取決於您對RoleDetail.Users
定義以及您使用它做了什么。
當您必須處理EF不喜歡的表達式時,備選方案和更普遍適用的解決方案是提前插入AsEnumerable
調用:
var query = Context.Roles
.Include("Users")
.Where(r => r.ID == id)
.AsEnumerable()
.Select(r => new RoleDetail() {
ID = r.ID,
Rolename = r.Rolename,
Active = r.Active,
Users = r.Users
.Select(u => new RoleDetail.RoleUser() {
ID = u.ID,
Username = u.Username
})
// .ToList()
})
.FirstOrDefault();
看起來它試圖在數據庫中執行ToList而不知道如何。 我會嘗試將其更改為ToArray ,或者失敗,只需將其保留為IEnumerable。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.