共用方式為


LINQ to DataSet 中的查詢

查詢是從數據源擷取數據的表達式。 查詢通常以特製化查詢語言表示,例如關係資料庫 SQL 和 XML 的 XQuery。 因此,開發人員必須針對所查詢的每個數據源或數據格式,學習新的查詢語言。 Language-Integrated 查詢 (LINQ) 提供更簡單、一致的模型,可用於處理各種數據源和格式的數據。 在 LINQ 查詢中,您一律會使用程式物件。

LINQ 查詢作業包含三個動作:取得數據源或來源、建立查詢,以及執行查詢。

您可以透過LINQ查詢實作泛型介面的 IEnumerable<T> 數據源。 呼叫AsEnumerableDataTable上會傳回一個實作泛型IEnumerable<T>介面的物件,這個介面作為LINQ to DataSet查詢的資料來源。

在查詢中,您可以指定您想要從數據源擷取的資訊。 查詢也可以指定該資訊在傳回之前應該如何排序、分組和成形。 在 LINQ 中,查詢會儲存在變數中。 如果查詢是設計來傳回值序列,則查詢變數本身必須是可列舉的類型。 此查詢變數不會採取任何動作,而且不會傳回任何數據;它只會儲存查詢資訊。 建立查詢之後,您必須執行該查詢以擷取任何數據。

在傳回值序列的查詢中,查詢變數本身絕不會保存查詢結果,而且只會儲存查詢命令。 查詢的執行會延後,直到在foreachFor Each迴圈中逐一查看查詢變數為止。 這稱為 延後執行;也就是說,查詢執行會在建構查詢之後一段時間發生。 這表示您可以視需要執行查詢的頻率。 例如,當您有其他應用程式正在更新的資料庫時,這會很有用。 在您的應用程式中,您可以建立查詢來擷取最新資訊,並重複執行查詢,每次傳回更新的資訊。

相較於會傳回值序列的延後查詢,會立即執行傳回單一值的查詢。 單一查詢的一些範例包括 CountMaxAverageFirst。 這些會立即執行,因為需要查詢結果才能計算單例結果。 例如,若要尋找查詢結果的平均值,必須執行查詢,讓平均函式具有要使用的輸入數據。 您也可以在查詢上使用 ToListToArray 方法,以強制立即執行不會產生單一值的查詢。 當您想要快取查詢結果時,強制立即執行這些技術會很有用。

查詢

LINQ to DataSet 查詢可以用兩種不同的語法來制定:查詢表達式語法和方法型查詢語法。

查詢表達式語法

查詢表達式是宣告式查詢語法。 此語法可讓開發人員以類似 SQL 的格式,以 C# 或 Visual Basic 撰寫查詢。 藉由使用查詢表達式語法,您甚至可以使用最少的程式代碼,對數據源執行複雜的篩選、排序和分組作業。 如需詳細資訊,請參閱 LINQ 查詢表示式基本查詢作業 (Visual Basic)

.NET Framework Common Language Runtime (CLR) 無法讀取查詢表達式語法本身。 因此,在編譯時期,查詢表達式會轉譯為CLR所瞭解的內容:方法呼叫。 這些方法稱為 標準查詢運算符。 身為開發人員,您可以選擇使用方法語法直接呼叫它們,而不是使用查詢語法。 如需詳細資訊,請參閱 LINQ 中的查詢語法和方法語法。 如需標準查詢運算符的詳細資訊,請參閱 標準查詢運算符概觀

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

// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable products = ds.Tables["Product"];

IEnumerable<DataRow> query =
    from product in products.AsEnumerable()
    select product;

Console.WriteLine("Product Names:");
foreach (DataRow p in query)
{
    Console.WriteLine(p.Field<string>("Name"));
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)

Dim products As DataTable = ds.Tables("Product")

Dim query = From product In products.AsEnumerable() _
            Select product
Console.WriteLine("Product Names:")
For Each p In query
    Console.WriteLine(p.Field(Of String)("Name"))
Next

Method-Based 查詢語法

制定 LINQ to DataSet 查詢的另一種方式是使用以方法為基礎的查詢。 以方法為基礎的查詢語法是LINQ運算符方法的直接方法呼叫序列,會將 Lambda 表達式當做參數傳遞。 如需詳細資訊,請參閱 Lambda 運算式

這個範例會使用 Select 來傳回 Product 的所有列,然後顯示產品名稱。

// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable products = ds.Tables["Product"];

var query = products.AsEnumerable().
    Select(product => new
    {
        ProductName = product.Field<string>("Name"),
        ProductNumber = product.Field<string>("ProductNumber"),
        Price = product.Field<decimal>("ListPrice")
    });

Console.WriteLine("Product Info:");
foreach (var productInfo in query)
{
    Console.WriteLine($"Product name: {productInfo.ProductName} Product number: {productInfo.ProductNumber} List price: ${productInfo.Price} ");
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)

Dim products As DataTable = ds.Tables("Product")

Dim query = products.AsEnumerable() _
    .Select(Function(product As DataRow) New With _
    { _
        .ProductName = product.Field(Of String)("Name"), _
        .ProductNumber = product.Field(Of String)("ProductNumber"), _
        .Price = product.Field(Of Decimal)("ListPrice") _
    })

Console.WriteLine("Product Info:")
For Each product In query
    Console.Write("Product name: " & product.ProductName)
    Console.Write("Product number: " & product.ProductNumber)
    Console.WriteLine("List price: $ " & product.Price)
Next

撰寫查詢

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

// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable products = ds.Tables["Product"];

IEnumerable<DataRow> productsQuery =
    from product in products.AsEnumerable()
    select product;

IEnumerable<DataRow> largeProducts =
    productsQuery.Where(p => p.Field<string>("Size") == "L");

Console.WriteLine("Products of size 'L':");
foreach (DataRow product in largeProducts)
{
    Console.WriteLine(product.Field<string>("Name"));
}

' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)

Dim products As DataTable = ds.Tables("Product")

Dim productsQuery = From product In products.AsEnumerable() _
                    Select product

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

Console.WriteLine("Products of size 'L':")
For Each product In largeProducts
    Console.WriteLine(product.Field(Of String)("Name"))
Next

執行查詢之後,就無法撰寫任何其他查詢,而且所有後續查詢都會使用記憶體內部LINQ運算元。 當您反覆執行foreach查詢變數或在For Each語句中進行操作,或者呼叫導致立即執行的其中一個 LINQ 轉換運算符時,就會發生查詢執行。 這些運算子包括: ToListToArrayToLookupToDictionary

在下列範例中,第一個查詢會傳回依標價排序的所有產品。 方法 ToArray 可用來強制立即執行查詢:

// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable products = ds.Tables["Product"];

IEnumerable<DataRow> query =
    from product in products.AsEnumerable()
    orderby product.Field<Decimal>("ListPrice") descending
    select product;

// Force immediate execution of the query.
IEnumerable<DataRow> productsArray = query.ToArray();

Console.WriteLine("Every price from highest to lowest:");
foreach (DataRow prod in productsArray)
{
    Console.WriteLine(prod.Field<Decimal>("ListPrice"));
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)

Dim products As DataTable = ds.Tables("Product")

Dim query = _
        From product In products.AsEnumerable() _
        Order By product.Field(Of Decimal)("ListPrice") Descending _
        Select product

' Force immediate execution of the query.
Dim productsArray = query.ToArray()

Console.WriteLine("Every price From highest to lowest:")
For Each prod In productsArray
    Console.WriteLine(prod.Field(Of Decimal)("ListPrice"))
Next

另請參閱