2015-09-08 22 views
16

匿名クラスはC#で読み取り専用のプロパティを持っています。これは、データベースから特定の値を取得するためにlinq selectクエリで宣言するためによく使用されます。 私のコードでは、次のようなクエリがあります。新しい文を使用して、匿名クラスの新しいオブジェクトを選択するのを混乱させるものです。モデルクラスはStudentClerkshipsLogModelでした。モデル名を使用すると、照会結果で編集が可能になります。匿名型とユーザー定義型のLINQ選択クエリ

var query = (from entity in _tblStudentClerkshipsLog.GetQueryable() 
      where entity.StudentID == intStudentID        
      select new StudentClerkshipsLogModel 
      { 
       StudentClerkshipID = entity.StudentClerkshipID, 
       StudentID = entity.StudentID, 
       ClerkshipID = entity.ClerkshipID, 
      }).ToList(); 

私はselect文でnew後のタイプについては言及しなかったとき、私は終了することができません。コンパイラはエラーを発生させます。無名のオブジェクトは読み取り専用です。

var query = (from entity in _tblStudentClerkshipsLog.GetQueryable() 
      where entity.StudentID == intStudentID        
      select new 
      { 
       StudentClerkshipID = entity.StudentClerkshipID, 
       StudentID = entity.StudentID, 
       ClerkshipID = entity.ClerkshipID, 
      }).ToList() 

私の質問は、linqが約2つのクエリを別々にバインドする方法です。どちらのクエリも動的バインディングを持っているか、最初は静的です。

おかげ

+3

「私は終了できません」とはどういう意味ですか?コンパイラはどのようなコードについて不平を言っていますか? (私はそれがあなたが示したコードだとは思っていません。)後でオブジェクトを修正しようとしていますか?その場合は、コードを表示してください。 –

+0

後でコードを修正したいのですが、選択クエリの違いを知る必要があるので、より良い選択をすることができます。 –

+1

@JonSkeet:それはタイプミスのようです。 "私は*編集できません*"。 – Dennis

答えて

11

を迷っている(そこにはどんなprivate setませんが、getのみ)のみのプロパティを読み取ります?

あなたはIQueryable<T>ためSelect拡張メソッドを呼び出すと、それはタイプExpression<Func<T, TResult>表現を受け入れます。あなたは、デバッガを使用して、生成された式に見ることができSelectのためのいくつかのスタブを書きます場合:

public static class MyExtensions 
{ 
    public static void MySelect<T, TResult>(this IQueryable<T> query, Expression<Func<T, TResult>> projection) 
    { 
     System.Diagnostics.Debug.WriteLine(projection); 
    } 
} 

違いは、コンパイラは名前付きの型と匿名型に対してラムダ式を生成する方法です。あなたが名前付きの型のためSelectを呼び出すと、式は次のようになります。です

{_ => new Person() {Id = _.Id, Name = _.Name}} 

は、まず新しいPersonオブジェクトが構築され、その後、メンバーは(MemberInit式)初期化されます。

しかし、あなたは匿名型のためSelectを呼び出すとき、式はコンストラクタ呼び出し(New式)として構築されます。

{_ => new <>f__AnonymousType0`2(a = _.Id, b = _.Name)} 

LINQプロバイダは、クエリ結果を実体化する場合、代表者にこれらのラムダをコンパイルし、そして最終的にはちょうどコンストラクタを呼び出し匿名型の場合

17

あなたが本当にLINQとは何の関係もありません取得しているエラー。あなたはすべてのLINQを使用せずに同じものを見ることができます:

var anonymous = new { Name = "Fred" }; 
anonymous.Name = "Joe"; // Error, as properties of anonymous types are read-only 

だから、あなたはあなたのLINQクエリによって取得されたオブジェクトを変更したい場合、あなたは匿名型を使用しないでください。しかし、両方のLINQクエリは静的にバインドされています。匿名型はコンパイル時には完全に認識されており、コンパイラは通常の型の制限を適用します。例えば:私が正しくあなたを理解していれば、あなたは彼らが「真」であるため、LINQプロバイダは、匿名オブジェクトのプロパティを設定することができますどのように、

var anonymous = new { Name = "Fred" }; 
Console.WriteLine(anonymous.Foo); // Error: no property Foo 
int bar = anonymous.Name; // Error: no conversion from string to int 
+0

これは知っていますが、クエリの動作が全く異なるためです。私は匿名のオブジェクトが読み取り専用であるということを言及していた –

2

I LINQ結果の匿名型の結果との違いが見つかりました。

  1. 結果が編集できません。グリッドビューに値を割り当てると、 は読み取り専用になります。

  2. 匿名オブジェクトの範囲に問題があります。 を別のメソッドに渡すことはできません。 var型のパラメータを定義する。 varは常に の後に初期化式を続ける必要があります。

結果が唯一の目的のために現在のコンテキストでのみ必要な場合は、匿名のクエリを使用してください。他の関数で結果が必要な場合は、オブジェクトの型を定義する必要があります。 newの後のオブジェクトタイプは、結果定義から得たいプロパティで作成され、次に中括弧{}で作成されます。 モデルクラスのすべての値を初期化する必要はありません。

関連する問題