ObjectQuery クラスは、エンティティ データ モデル (EDM) に対する LINQ to Entities クエリと Entity SQL クエリの両方をサポートしています。ObjectQuery は、Entity SQL に相当するクエリ コマンドを順番に構築するために使用できるクエリ ビルダ メソッドのセットも実装します。次の表に、ObjectQuery のクエリ ビルダ メソッドおよび等価の Entity SQL ステートメントを示します。
ObjectQuery メソッド | Entity SQL ステートメント |
---|---|
それぞれのクエリ ビルダ メソッドは、ObjectQuery の新しいインスタンスを返します。そのため、先行する ObjectQuery インスタンスのシーケンスの操作に基づいた結果セットのクエリを作成できます。次の例は、Where メソッドを使用して、ProductID によって返された Product オブジェクトをフィルタする方法を示します。
' Return Product objects with the specified ID.
Dim query As ObjectQuery(Of Product) = _
advWorksContext.Product _
.Where("it.ProductID = @product", _
New ObjectParameter("product", productId))
// Return Product objects with the specified ID.
ObjectQuery<Product> query =
advWorksContext.Product
.Where("it.ProductID = @product",
new ObjectParameter("product", productId));
ObjectQuery は IQueryable および IEnumerable を実装しているので、ObjectQuery に実装されるクエリ ビルダ メソッドを LINQ 固有の標準クエリ演算子メソッド (First や Count など) と組み合わせることが可能です。クエリ ビルダ メソッドとは異なり、LINQ 演算子では、ObjectQuery が返されません。詳細については、Visual Studio 2008 ドキュメントの「標準クエリ演算子の概要」を参照してください。
データの選択
既定では、ObjectQuery は、0 個以上の特定の型のエンティティ オブジェクトを返します。後続のクエリ メソッド (Where や OrderBy など) を呼び出すと、元の ObjectQuery によって返されるオブジェクトのコレクションに影響します。Select や GroupBy などのメソッドは、エンティティ型ではなく、DbDataRecord としてデータの投影を返します。詳細については、「オブジェクト クエリ (Entity Framework)」を参照してください。次の例では、入れ子になった SalesOrderHeader エンティティ型を含む DbDataRecord オブジェクトのコレクションが返されます。
' Define a query that returns a nested
' DbDataRecord for the projection.
Dim query As ObjectQuery(Of DbDataRecord) = _
advWorksContext.Contact.Select("it.FirstName, " _
+ "it.LastName, it.SalesOrderHeader") _
.Where("it.LastName = 'Zhou'")
// Define a query that returns a nested
// DbDataRecord for the projection.
ObjectQuery<DbDataRecord> query =
advWorksContext.Contact.Select("it.FirstName, "
+ "it.LastName, it.SalesOrderHeader")
.Where("it.LastName = 'Zhou'");
クエリ ビルダ メソッドは順番に適用されますが、Entity SQL でサポートされている、同じタイプの入れ子になったサブクエリを作成することも可能です。そのためには、サブクエリを Entity SQL としてメソッドに含める必要があります。次の例では、Select メソッド内で Entity SQL SELECT サブクエリを使用して LastName レコードを含めています。これらのレコードは、結果セットで入れ子になり、姓の最初の文字でアルファベット順に並べ替えられます。
' Define the query with a GROUP BY clause that returns
' a set of nested LastName records grouped by first letter.
Dim query As ObjectQuery(Of DbDataRecord) = _
advWorksContext.Contact _
.GroupBy("SUBSTRING(it.LastName, 1, 1) AS ln", "ln") _
.Select("it.ln AS ln, (SELECT c1.LastName " + _
"FROM AdventureWorksEntities.Contact AS c1 " + _
"WHERE SubString(c1.LastName, 1, 1) = it.ln) AS CONTACT") _
.OrderBy("it.ln")
// Define the query with a GROUP BY clause that returns
// a set of nested LastName records grouped by first letter.
ObjectQuery<DbDataRecord> query =
advWorksContext.Contact
.GroupBy("SUBSTRING(it.LastName, 1, 1) AS ln", "ln")
.Select("it.ln AS ln, (SELECT c1.LastName " +
"FROM AdventureWorksEntities.Contact AS c1 " +
"WHERE SubString(c1.LastName, 1, 1) = it.ln) AS CONTACT")
.OrderBy("it.ln");
[!メモ]
ObjectQuery によって生成されるデータ ソース コマンドを表示するには、ToTraceString メソッドを使用します。詳細については、「オブジェクト クエリ (Entity Framework)」を参照してください。
別名
クエリ ビルダ メソッドが順番に適用されると、累積クエリ コマンドが構築されます。これは、現在の ObjectQuery コマンドが、現在のメソッドの適用先であるサブクエリのように扱われることを意味します。
[!メモ]
CommandText プロパティは、ObjectQuery インスタンスに対するコマンドを返します。
クエリ ビルダ メソッドでは、別名を使用して現在の ObjectQuery コマンドを参照します。次の例に示すように、既定では、文字列 "it" は現在のコマンドを表す別名です。
' Return Product objects with a standard cost
' above $10.
Dim productQuery As ObjectQuery(Of Product) = _
advWorksContext.Product _
.Where("it.StandardCost > 10")
// Return Product objects with a standard cost
// above $10.
ObjectQuery<Product> productQuery =
advWorksContext.Product
.Where("it.StandardCost > 10");
ObjectQuery の Name プロパティを設定すると、その値が後続のメソッドでの別名になります。次の例では、ObjectQuery の名前を "product" に変更して、この別名を後続の OrderBy メソッドで使用することにより、前の例を拡張しています。
' Return Product objects with a standard cost
' above $10.
Dim productQuery As ObjectQuery(Of Product) = _
advWorksContext.Product _
.Where("it.StandardCost > 10")
'Set the Name property for the query and then
' use that name as the alias in the subsequent
' OrderBy method.
productQuery.Name = "product"
Dim filteredProduct As ObjectQuery(Of Product) = _
productQuery.OrderBy("product.ProductID")
// Return Product objects with a standard cost
// above $10.
ObjectQuery<Product> productQuery =
advWorksContext.Product
.Where("it.StandardCost > 10");
// Set the Name property for the query and then
// use that name as the alias in the subsequent
// OrderBy method.
productQuery.Name = "product";
ObjectQuery<Product> filteredProduct = productQuery
.OrderBy("product.ProductID");
パラメータ
Entity SQL 文字列入力を受け取るすべてのクエリ ビルダ メソッドは、パラメータ化クエリもサポートします。Entity SQL 内のパラメータ名は、クエリ式の中で、先頭に @ 記号を付けることによって定義します。詳細については、「パラメータ (Entity SQL)」を参照してください。パラメータは、ObjectParameter インスタンスの配列としてクエリ ビルダ メソッドに渡されます。次の例では、2 つのパラメータを Where メソッドに渡しています。
' Get the contacts with the specified name.
Dim contactQuery As ObjectQuery(Of Contact) = _
context.Contact _
.Where("it.LastName = @ln AND it.FirstName = @fn", _
New ObjectParameter("ln", lastName), _
New ObjectParameter("fn", firstName))
// Get the contacts with the specified name.
ObjectQuery<Contact> contactQuery = context.Contact
.Where("it.LastName = @ln AND it.FirstName = @fn",
new ObjectParameter("ln", lastName),
new ObjectParameter("fn", firstName));
パラメータを使用する際の注意点
クエリ ビルダ メソッドでパラメータを使用する際は、次の点に注意してください。
クエリ ビルダ メソッドに渡されるパラメータは、シーケンスで ObjectQuery の後続のインスタンスによって集計されます。これらのパラメータには、Parameters プロパティを使用してアクセスできます。クエリがコンパイルまたは実行されていない限り、パラメータを追加した後で、コレクションからパラメータを削除することも、コレクションをクリアすることもできます。パラメータ名は変更できませんが、値はいつでも変更できます。
パラメータは、ObjectParameterCollection 内で一意である必要があります。コレクション内に同じ名前のパラメータが 2 つ存在することはできません。
Union、UnionAll、Intersect、および Except などの結合メソッドを使用すると、パラメータ コレクションが結合されます。パラメータのセットに互換性がない場合、パラメータのセットが不完全な場合、または両方のクエリのパラメータ コレクションに同じ名前が存在する場合、例外がスローされます。
参照
概念
オブジェクトとしてのデータのクエリ (Entity Framework)
クエリ結果の構造化 (Entity Framework)