LINQ to Entities クエリがコマンド ツリーに変換されて実行されると、通常、クエリ結果は次のいずれかとして返されます。
0 個以上の型指定されたエンティティ オブジェクトのコレクション、または概念モデルの複合型のプロジェクション。
概念モデルでサポートされる CLR 型。
インライン コレクション。
匿名型。
クエリがデータ ソースに対して実行されると、結果は CLR 型に具体化され、クライアントに返されます。 すべてのオブジェクトの具体化は、Entity Framework によって実行されます。 Entity Framework と CLR とのマッピングができないことが原因でエラーが発生すると、オブジェクトの具体化中に例外がスローされます。
クエリ実行がプリミティブ概念モデル型を返す場合、結果はスタンドアロンで Entity Framework から切断された CLR 型で構成されます。 ただし、クエリが ObjectQuery<T>で表される型指定されたエンティティ オブジェクトのコレクションを返す場合、それらの型はオブジェクト コンテキストによって追跡されます。 すべてのオブジェクトの動作 (子/親コレクション、変更の追跡、ポリモーフィズムなど) は、Entity Framework で定義されています。 この機能は、Entity Framework で定義されている容量で使用できます。 詳細については、「 オブジェクトの操作」を参照してください。
クエリから返される構造体型 (匿名型や null 許容複合型など) には、 null
値を指定できます。 返されるエンティティの EntityCollection<TEntity> プロパティは、 null
値にすることもできます。 これは、要素を持たないnull
でFirstOrDefaultを呼び出すなど、ObjectQuery<T>値のエンティティのコレクション プロパティを投影することによって発生する可能性があります。
特定の状況では、クエリの実行中に具体化された結果が生成されるように見えることがありますが、クエリはサーバーで実行され、エンティティ オブジェクトは CLR で具体化されません。 これは、オブジェクトの具体化の副作用に依存している場合に問題を引き起こす可能性があります。
次の例には、MyContact
プロパティを持つカスタム クラス LastName
が含まれています。 LastName
プロパティを設定すると、count
変数がインクリメントされます。 次の 2 つのクエリを実行すると、最初のクエリは count
インクリメントされますが、2 番目のクエリはインクリメントされません。 これは、2 番目のクエリでは、 LastName
プロパティが結果から投影され、ストアでクエリを実行する必要がないため、 MyContact
クラスは作成されないためです。
public static int count = 0;
static void Main(string[] args)
{
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
var query1 = AWEntities
.Contacts
.Where(c => c.LastName == "Jones")
.Select(c => new MyContact { LastName = c.LastName });
// Execute the first query and print the count.
query1.ToList();
Console.WriteLine("Count: " + count);
//Reset the count variable.
count = 0;
var query2 = AWEntities
.Contacts
.Where(c => c.LastName == "Jones")
.Select(c => new MyContact { LastName = c.LastName })
.Select(my => my.LastName);
// Execute the second query and print the count.
query2.ToList();
Console.WriteLine("Count: " + count);
}
Console.WriteLine("Hit enter...");
Console.Read();
}
Public count As Integer = 0
Sub Main()
Using AWEntities As New AdventureWorksEntities()
Dim query1 = AWEntities.Contacts _
.Where(Function(c) c.LastName = "Jones") _
.Select(Function(c) New MyContact With {.LastName = c.LastName})
' Execute the first query and print the count.
query1.ToList()
Console.WriteLine("Count: " & count)
' Reset the count variable.
count = 0
Dim query2 = AWEntities _
.Contacts() _
.Where(Function(c) c.LastName = "Jones") _
.Select(Function(c) New MyContact With {.LastName = c.LastName}) _
.Select(Function(x) x.LastName)
' Execute the second query and print the count.
query2.ToList()
Console.WriteLine("Count: " & count)
End Using
End Sub
public class MyContact
{
String _lastName;
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName = value;
count++;
}
}
}
Public Class MyContact
Private _lastName As String
Public Property LastName() As String
Get
Return _lastName
End Get
Set(ByVal value As String)
_lastName = value
count += 1
End Set
End Property
End Class