共用方式為


LINQ to Entities 中的查詢

查詢是指從資料來源中擷取資料的運算式。查詢通常會以特定的查詢語言來表示,例如 SQL 用於關聯式資料庫,而 XQuery 用於 XML。因此,開發人員必須針對他們所查詢的每種資料來源或資料格式,學習新的查詢語言。Language-Integrated Query (LINQ) 提供了一種較簡單且一致的模型,可處理各種資料來源和格式的資料。在 LINQ 查詢中,您一定會使用程式設計物件。

LINQ 查詢作業由三個動作構成:取得資料來源、建立查詢和執行查詢。

實作 IEnumerable 泛型介面或 IQueryable 泛型介面的資料來源可以透過 LINQ 進行查詢。實作泛型 IQueryable 介面之泛型 ObjectQuery 類別的執行個體會當做 LINQ 到實體 查詢的資料來源。ObjectQuery 泛型類別表示傳回具型別實體之執行個體或集合的查詢。開發人員會從 ObjectContext 建構執行個體,這是以 CLR 物件形式與 實體資料模型 (EDM) 互動的主要類別。

在此查詢中,您可以精確地指定想要從資料來源中擷取的資訊。此外,查詢也可以指定該項資訊傳回之前應該如何排序、分組和成形。在 LINQ 中,查詢會儲存在變數內。如果查詢傳回一連串值,查詢變數本身必須是可查詢型別。這個查詢變數不會採取任何動作,也不會傳回任何資料。它只會儲存查詢資訊。在您建立查詢之後,必須執行該查詢以便擷取任何資料。

在傳回值序列的查詢中,查詢變數本身絕不會保存查詢結果,只會儲存查詢命令而已。查詢的執行會延後,直到在 foreachFor Each 迴圈 (Loop) 中反覆查看查詢變數為止。這就是所謂的*「延後執行」*;換言之,查詢的執行是在此查詢建構好一段時間之後發生。這表示您可以隨時都可以執行查詢。例如,當您擁有一個正由其他應用程式更新的資料庫時,這就很有用。您可以在應用程式中建立擷取最新資訊的查詢,然後重複執行此查詢,以便每次都傳回更新的資訊。

相較於傳回值序列的延後查詢,傳回單一子句值的查詢會立即執行。單一子句查詢的某些範例包括 CountMaxAverageFirst。這些查詢會立即執行,因為必須有這些查詢結果才能計算單一結果。此外,您也可以針對查詢使用 ToListToArray 方法,強制立即執行不會產生單一子句值的查詢。當您想要快取查詢的結果時,這些強制立即執行的技巧就很有用。如需延後和立即查詢執行的詳細資訊,請參閱 LINQ 簡介

查詢

LINQ 到實體 查詢可以使用兩個不同的語法來撰寫:查詢運算式語法和以方法為基礎的查詢語法。查詢運算式語法是 C# 3.0 和 Visual Basic 9.0 中的新項目,是由類似 Transact-SQL 或 XQuery 的宣告式語法撰寫的一組子句所構成。不過,.NET Framework Common Language Runtime (CLR) 無法讀取查詢運算式語法本身。因此,在編譯階段,查詢運算式會轉譯為 CLR 所不了解的方法呼叫。這些方法就是所謂的*「標準查詢運算子」*。身為開發人員,您可以選擇使用方法語法來直接呼叫它們,而非使用查詢語法。如需詳細資訊,請參閱查詢語法與方法語法的比較 (LINQ)。如需如何使用標準查詢運算子的詳細資訊,請參閱 LINQ 程式設計手冊概論

查詢運算式語法

查詢運算式是宣告式查詢語法。這些語法可以讓開發人員以類似 Transact-SQL 格式的高階語言撰寫查詢。透過使用查詢運算式語法,您就可以利用最少的程式碼,針對資料來源執行同樣複雜的篩選、排序和分組作業。如需詳細資訊,請參閱 LINQ 查詢運算式 (C# 程式設計手冊)基本查詢作業 (Visual Basic)

下列範例會使用 Select 來傳回 Product 中的所有資料列,並顯示產品名稱。

Using AWEntities As New AdventureWorksEntities
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productNames = _
       From p In products _
       Select p.Name

    Console.WriteLine("Product Names:")
    For Each productName In productNames
        Console.WriteLine(productName)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<string> productNames =
       from p in products
       select p.Name;

    Console.WriteLine("Product Names:");
    foreach (var productName in productNames)
    {
        Console.WriteLine(productName);
    }
}

以方法為基礎的查詢語法

另一種撰寫 LINQ 到實體 查詢的方式是使用以方法為基礎的查詢。以方法為基礎的查詢語法是對 LINQ 運算子方法之直接方法呼叫的序列,並傳遞 Lambda 運算式當做參數。如需詳細資訊,請參閱 Lambda 運算式 (C# 程式設計手冊)

這則範例會使用 Select 來傳回 Product 資料表中的所有資料列,並顯示產品名稱。

Using AWEntities As New AdventureWorksEntities


    Dim productNames = AWEntities.Product.Select(Function(p) p.Name)


    Console.WriteLine("Product Names:")
    For Each productName In productNames
        Console.WriteLine(productName)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<string> productNames = products.Select(p => p.Name);


    Console.WriteLine("Product Names:");
    foreach (var productName in productNames)
    {
        Console.WriteLine(productName);
    }
}

撰寫查詢

如本主題先前所述,當查詢設計為傳回值的序列時,查詢變數本身只會儲存查詢命令。如果查詢沒有包含將導致立即執行的方法,查詢的實際執行將延後,直到您在 foreachFor Each 迴圈中反覆查看查詢變數為止。延後執行可結合多個查詢或擴充單一查詢。擴充單一查詢時,它會修改成包含新的作業,而且最終的執行將反映這些變更。在下列範例中,第一個查詢會傳回所有產品。第二個查詢會使用 Where 來擴充第一個查詢,以便傳回大小為 "L" 的所有產品:

Using AWEntities As New AdventureWorksEntities()
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productsQuery = _
        From p In products _
        Select p

    Dim largeProducts = _
        productsQuery.Where(Function(p) p.Size = "L")

    Console.WriteLine("Products of size 'L':")
    For Each product In largeProducts
        Console.WriteLine(product.Name)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{

    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<Product> productsQuery =
        from p in products
        select p;

    IQueryable<Product> largeProducts = productsQuery.Where(p => p.Size == "L");

    Console.WriteLine("Products of size 'L':");
    foreach (var product in largeProducts)
    {
        Console.WriteLine(product.Name);
    }
}

在查詢執行之後,所有後續查詢都會使用記憶體中的 LINQ 運算子。使用 foreachFor Each 陳述式或呼叫其中一個 LINQ 轉換運算子來重複處理查詢變數,將會造成立即執行。這些轉換運算子包咶:ToListToArrayToLookupToDictionary

在下列範例中,第一個查詢會傳回所有產品。第二個查詢是在第一個查詢執行加以擴充,用來傳回紅色的產品。

Using AWEntities As New AdventureWorksEntities()
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productsQuery = _
        From p In products _
        Select p

    Console.WriteLine("The list of products:")
    For Each Product As Product In productsQuery
        Console.WriteLine(Product.Name)
    Next

    Dim redProducts = productsQuery _
        .Where(Function(p) p.Color = "Red") _
        .Select(Function(p) p)

    Console.WriteLine("")
    Console.WriteLine("The list of red products:")
    For Each redProduct As Product In redProducts
        Console.WriteLine(redProduct.Name)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{

    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<Product> productsQuery =
        from p in products
        select p;

    Console.WriteLine("The list of products:");
    foreach (Product product in productsQuery)
    {
        Console.WriteLine(product.Name);
    }

    IQueryable<Product> redProducts = productsQuery
        .Where(p => p.Color == "Red")
        .Select(p => p);

    Console.WriteLine("");
    Console.WriteLine("The list of red products:");
    foreach (Product redProduct in redProducts)
    {
        Console.WriteLine(redProduct.Name);
    }

}

另請參閱

其他資源

LINQ to Entities
使用 C# 撰寫 LINQ 入門
使用 Visual Basic 撰寫 LINQ 入門