簡體   English   中英

Linq查詢返回復雜類型

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM