匿名クラスはc#で読み取り専用のプロパティを持っています。これは、linq選択クエリで宣言してデータベースから特定の値を取得するためによく使用されます。私のコードには次のクエリがあります。newステートメントを使用して匿名クラスの新しいオブジェクトを選択するのを混乱させたもの。 StudentClerkshipsLogModel
のモデルクラスがありました。モデル名を使用すると、クエリ結果で編集が可能になります。
var query = (from entity in _tblStudentClerkshipsLog.GetQueryable()
where entity.StudentID == intStudentID
select new StudentClerkshipsLogModel
{
StudentClerkshipID = entity.StudentClerkshipID,
StudentID = entity.StudentID,
ClerkshipID = entity.ClerkshipID,
}).ToList();
new
ステートメントでselect
の後にタイプについて言及しなかった場合、終了できません。コンパイラはエラーを発生させます。匿名オブジェクトは読み取り専用です。
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つのクエリを異なる方法でバインドする方法です。両方のクエリに動的バインディングがあるか、最初のクエリは静的です。
ありがとう
私が正しく理解しているとしたら、LINQプロバイダーは匿名オブジェクトのプロパティをどのように設定できるのでしょうか。それらは "true"の読み取り専用プロパティです(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
expression)として式が作成されます。
{_ => new <>f__AnonymousType0`2(a = _.Id, b = _.Name)}
LINQプロバイダーは、クエリ結果を具体化するときに、これらのラムダをデリゲートにコンパイルし、最終的には匿名型のコンストラクターを呼び出すだけです。
あなたが得ているエラーは本当にLINQとは何の関係もありません。 LINQをまったく使用しなくても同じことがわかります。
var anonymous = new { Name = "Fred" };
anonymous.Name = "Joe"; // Error, as properties of anonymous types are read-only
そのため、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
LINQ結果の匿名型の結果との次の違いが見つかりました。
結果は編集可能ではありません。グリッドビューに値を割り当てると、読み取り専用になります。
匿名オブジェクトのスコープに問題があります。タイプを別のメソッドに渡すことができません。タイプvarのパラメーターを定義します。 varの後には必ず初期化式を続ける必要があります。
現在のコンテキストでのみ読み取り専用の結果が必要な場合は、匿名クエリを使用してください。他の関数で結果が必要な場合は、オブジェクトのタイプを定義する必要があります。 new
の後のオブジェクトタイプは、結果定義から取得するプロパティを使用して作成され、中括弧{}
。モデルクラスのすべての値を初期化する必要はありません。