4

私はユーザーとロールのかなり標準的なモデルを持っています:

+-------+   +-----------+   +-------+
| 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とあまり仕事をしていないので、クエリがどういうわけか間違っていると確信しています。誰かが私のクエリがどこで間違っているのか、そして私が達成しようとしていることを達成するためのより良い方法があるかどうかを教えてもらえますか?

前もって感謝します!

4

3 に答える 3

3

linq-to-entitiesの経験はほとんどないので、これは暗闇の中でのショットです。

なぜ.ToList()が必要なのですか?

.Select()はすでにIEnumerableを返すため、なくても機能するはずです。

ToList()は、リストを返します。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();
于 2012-04-28T16:15:48.117 に答える
2

EF LINQプロバイダーに送信されるLINQクエリ内のすべては、L2EがSQLに直接変換できる式である必要があります。EFが変換できる部分を、LINQ2オブジェクトで実行する必要のある部分から手動で分離するのはあなた次第です。

実行は、クエリを実際に列挙する必要があるポイント(この場合はFirstOrDefault呼び出し)で行われます。IQueryable.AsEnumerable();を呼び出すことにより、クエリを強制的に先に実行することができます。その後は、LINQ 2オブジェクトによって処理され、ほとんど何でも実行できます。

あなたの場合、ラムダ式の翻訳不可能な側面は、への呼び出しToListだけです。これには同等のデータベースがないため、単純にそれを呼び出すことはできません。これの欠点は、EFの実装のUsers結果である任意の内部クラスがプロパティに設定されることです。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();
于 2012-04-28T16:34:38.253 に答える
1

データベースでToListを実行しようとしていて、方法がわからないようです。ToArrayに変更するか、失敗してIEnumerableのままにしてみます。

于 2012-04-28T16:18:41.533 に答える