物件查詢 (Entity Framework)

ObjectQuery 泛型類別表示可以傳回零個或多個具型別物件之集合的查詢。 ObjectQuery 屬於 ObjectContext,其中包含撰寫及執行查詢所需的連接和中繼資料資訊。 您可以使用 new 運算子建構 ObjectQuery,並將查詢字串和物件內容傳遞給建構函式。 不過,更常見的情況是在 ObjectContext 衍生類別上使用屬性,以取得代表實體集之集合的 ObjectQuery 執行個體。 ObjectContext 通常會透過 Entity Framework 工具所產生之類別或您的 POCO 類別進行子類別化,而物件內容上的屬性會傳回實體集當做 ObjectQuery (在 .NET Framework 3.5 版 SP1 中) 或當做 ObjectSet (在 .NET Framework 4 版中)。 ObjectSet 類別會擴充 ObjectQuery 類別來提供功能,例如在具型別實體集的內容中加入及刪除物件。

預設的 ObjectQuery 會提供開始查詢,傳回指定之類型的所有實體。 此查詢可以使用 LINQ to Entities 或查詢產生器方法來進一步調整。

下列範例會查詢 Products 之集合的物件內容。

Using context As New AdventureWorksEntities
    Dim products As ObjectSet(Of Product) = context.Products

    Dim productsQuery = _
        From product In products _
        Select product

    Console.WriteLine("Product Names:")
    For Each product In productsQuery
        Console.WriteLine(product.Name)
    Next
End Using
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    IQueryable<Product> productsQuery = from product in context.Products
                                        select product;

    Console.WriteLine("Product Names:");
    foreach (var prod in productsQuery)
    {
        Console.WriteLine(prod.Name);
    }
}

查詢執行

發生於執行物件查詢時:

請注意,如果查詢執行的結果,沒有從資料來源傳回任何結果,則結果將包含一個空集合而不是 null

由 Entity Framework 所執行的查詢會針對資料來源中的資料進行評估,而且結果將不會反映物件內容中的新物件。 如果具有與正在查詢之實體相同識別的實體已經附加到內容中,則會根據查詢的 MergeOption 將資料來源中的資料與內容中已經存在的資料合併在一起。 若要取得快取中的資料,請在 ObjectStateManager 類別上使用 GetObjectStateEntries 方法。 ObjectStateManager 會管理物件內容中物件的狀態,所以如果您想要取得所有已經加入、修改及未變更的物件,您可以將下列 EntityState 值的位元 OR 傳遞給 GetObjectStateEntries 方法:AddedModifiedUnchanged。 如需詳細資訊,請參閱示範如何執行本機查詢的部落格 (英文)。

在下列範例中,會呼叫 Execute 方法來執行查詢:

Using context As New AdventureWorksEntities()
    Dim query As ObjectSet(Of Product) = context.Products

    ' Execute the query and get the ObjectResult. 
    Dim queryResult As ObjectResult(Of Product) = query.Execute(MergeOption.AppendOnly)
    ' Iterate through the collection of Product items. 
    For Each result As Product In queryResult
        Console.WriteLine("{0}", result.Name)
    Next
End Using
using (AdventureWorksEntities context =
    new AdventureWorksEntities())
{
    ObjectSet<Product> query = context.Products;

    // Execute the query and get the ObjectResult.
    ObjectResult<Product> queryResult = query.Execute(MergeOption.AppendOnly);
    // Iterate through the collection of Product items.
    foreach (Product result in queryResult)
        Console.WriteLine("{0}", result.Name);
}

查詢投影

物件查詢通常用來傳回概念模型資料做為實體物件,但是它們可能也會針對巢狀結果和匿名投影傳回 DbDataRecord 物件,或者它們可以針對單一值組傳回基本 CLR 型別。

LINQ to Entities 和 Entity SQL 都支援查詢投影。 以下是適用於查詢投影的考量因素:

  • 某些擴充方法必須將許多結果的集合當做輸入。 如果 ObjectQuery 代表的查詢會傳回具有單一純量結果的集合,而且呼叫了這些擴充方法的其中一個,則會擲回 ArgumentException,如下列範例所示。

    ' Define a query projection that returns 
    ' a collection with a single scalar result.
    Dim scalarQuery As New ObjectQuery(Of Int32)("100", context)
    
    ' Calling an extension method that requires a collection 
    ' will result in an exception. 
    Dim hasValues As Boolean = scalarQuery.Any()
    
    // Define a query projection that returns 
    // a collection with a single scalar result.
    ObjectQuery<Int32> scalarQuery =
        new ObjectQuery<Int32>("100", context);
    
    // Calling an extension method that requires a collection
    // will result in an exception.
    bool hasValues = scalarQuery.Any();
    
  • 如果 ObjectQuery 在投影為基本型別時可能會傳回 null 值,您應該使用此型別可為 Null 的版本。 下列查詢使用可為 Null 的 DateTime,因為 SalesOrderHeader 物件的 ShipDate 屬性可能會傳回 null 值。

    Dim shipDateQuery As ObjectQuery(Of Nullable(Of DateTime)) = _
        context.SalesOrderHeaders.Where("it.CustomerID = @contactId", _
            New ObjectParameter("contactId", contactId)).SelectValue(Of Nullable(Of DateTime))("it.ShipDate")
    
    ObjectQuery<Nullable<DateTime>> shipDateQuery =
        context.SalesOrderHeaders
        .Where("it.CustomerID = @contactId",
            new ObjectParameter("contactId", contactId))
        .SelectValue<Nullable<DateTime>>("it.ShipDate");
    

    如需詳細資訊,請參閱可為 Null 的型別 (Visual Basic 程式設計指南)Nullable Types (C# Programming Guide)

檢視儲存命令

當您查詢概念模型時,Entity Framework 會將根據概念模型的 LINQ to Entities 和 Entity SQL 查詢轉換成針對資料來源的同等查詢。 Entity Framework 會提供 System.Data.Objects.ObjectQuery.ToTraceStringSystem.Data.EntityClient.EntityCommand.ToTraceString 方法,它們可讓您在執行階段檢視這些儲存命令,而不必針對資料來源執行追蹤。 如需詳細資訊,請參閱 HOW TO:檢視存放區命令 (Entity Framework)

根據物件的 EntityKey 來擷取物件

如果您知道某個實體的機碼值 (Key Value),您可以從資料來源擷取它,而不需要明確建立和執行物件查詢。 ObjectContext 上的 GetObjectByKeyTryGetObjectByKey 方法會將具有指定 EntityKey 的物件傳回到物件內容中。 當您使用 GetObjectByKey 時,您必須在提供的 EntityKey 未對應到現有實體時處理 ObjectNotFoundException。 如需詳細資訊,請參閱 HOW TO:使用特定物件的索引鍵傳回此物件 (Entity Framework)

另請參閱

概念

查詢概念模型 (Entity Framework)
使用 ObjectSet (Entity Framework)
已編譯的查詢 (LINQ to Entities)