2012-04-28 3 views
3

は、私はユーザーとロールのためにかなり標準モデルを持っていますViewModelには、以下のdefinied:LINQのクエリの複合型を返すために

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 does not recognize the method 'System.Collections.Generic.List [RolesRepository+RoleDetail+RoleUser] ToList[RoleUser] (System.Collections.Generic.IEnumerable[RolesRepository+RoleDetail+RoleUser])' method, and this method cannot be translated into a store expression.

私は多くのLinqと仕事をしていないので、私の質問は何とか間違っていると確信しています。誰かが私の質問がどこに間違っているのか、私が達成しようとしていることを伝える良い方法があるのか​​を私に見せてもらえますか?

ありがとうございます!

+1

代わり、あなたはEFが好きではないという表現を処理する必要があり、より一般的に適用可能な解決策は、早期AsEnumerable呼び出しを挿入することです。 ToList() '? –

+0

それは問題であったと思われます。誰もが答えを残してくれてありがとう! – BradBrening

答えて

2

LINQツーエンティティリトル経験なので、これは暗闇の中でショットです:

は、なぜあなたは.ToListが必要なのですか()?

.Select()はすでにIEnumerableを返しています。

ToList()は、IListや同様のインターフェイスではなく、具象的なC#クラスを返します。だから私は、LinqがEntityにシーンのシンタックスの背後でそれを翻訳することはできないと想像したいと思います。

これは機能しますか?

 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(); 
+0

それを取り除くことはトリックでした - ありがとう!私はコレクションを反復することができる前に、私のリポジトリのコンストラクタ/デストラクタの基底クラスを介してインスタンス化/配置されたEntitiesクラスが破棄されるため、.ToList()を使用しています。これはおそらく他のすべての問題ですが、ToList()は動作しているようです(通常)。 – BradBrening

1

データベースでToListメソッドを実行しようとするとどのように知っていないように見えます。私はToArrayに変更しようとするか、失敗してIEnumerableとして残してみます。

+0

+1アシスタンスに感謝します。最初の答えに基づいて受け入れましたが、どこでも役立ちます。 – BradBrening

2

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

実行は、クエリが実際に列挙される必要がある時点で実行されます。その場合は、FirstOrDefault呼び出しです。 IQueryable.AsEnumerable()を呼び出すと、クエリを先に強制的に実行することができます。それ以降のものはLINQ 2オブジェクトによって処理され、あなたが望むものは何でもできます。

ラムダ式の変換できない唯一の側面は、ToListへの呼び出しです。これにはデータベースに相当するものはありません。したがって、単に呼び出すことはできません。これの欠点は、UsersプロパティがEFの実装でIQueryable.Selectという結果になる任意の内部クラスを設定されることです。それは、RoleDetail.Usersをあなたが定義したものと、それをどうするかに応じて、あなたにとって問題かもしれません。あなたが `削除する場合はどうなります

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(); 
+0

優秀な説明。したがって、一度.AsEnumerableが呼び出されると、クエリは実際のエンティティオブジェクトを扱うのに対して、dbの親和性のあるSQLクエリを作成しようとしていますか?それは私には意味がある。 – BradBrening

+0

はい。 EF LINQシーケンス演算子は 'IQueryable'オブジェクトを返します。これらはまだコンパイルされていない 'Expression'を含んでいます(そして決してそれはSQLクエリを生成するために使われることはありません)。 'IQueryable'を返さないメソッドを呼び出すと、EFは式を解析し、S​​QLを実行し、オブジェクト/シーケンスを生成する必要があります。それが終わると、EFは外れてしまいます。 –

+0

これはおそらく私のコントローラがIQueryableオブジェクトを私のビューに返すのがエラーを投げている理由を説明しています - dbコンテキストが範囲外で、実際のSQLはまだ実行されていませんでしたか? – BradBrening

関連する問題