Share via


LINQ 考量 (WCF Data Services)

本主題所提供的資訊是關於您要使用 WCF Data Services 用戶端時所撰寫和執行 LINQ 查詢的方式,以及使用 LINQ 查詢實作 Open Data Protocol (OData) 之資料服務的限制。如需詳細資訊針對 OData 型資料服務撰寫和執行查詢的詳細資訊,請參閱查詢資料服務 (WCF Data Services)

撰寫 LINQ 查詢

LINQ 可讓您針對實作 IEnumerable 之物件的集合,撰寫查詢。Visual Studio 中的 [加入服務參考] 對話方塊和 DataSvcUtil.exe 工具都是用來產生 OData 服務的表示法,作為繼承自 DataServiceContext 的實體容器類別,以及表示摘要中傳回之實體的物件。這些工具也會針對服務公開為摘要的集合,產生實體容器類別的屬性。封裝資料服務之類別的這些每個屬性都會傳回 DataServiceQuery。因為 DataServiceQuery 類別會實作由 LINQ 定義的 IQueryable 介面,也就是 WCF Data Services ,因此,您可以根據資料服務所公開的摘要撰寫 LINQ 查詢,這些摘要會由用戶端程式庫轉換為執行時傳送至資料服務的查詢要求 URI。

Ee622463.Important(zh-tw,VS.100).gif 注意:
可以用 LINQ 語法表示的查詢集合會比在 OData 資料服務所使用之 URI 語法中啟用的查詢集合更廣泛。當查詢無法對應至目標資料服務中的 URI 時,就會引發 NotSupportedException。如需詳細資訊,請參閱本主題中的Unsupported LINQ Methods。

下列範例是 LINQ 查詢,它會傳回運費成本超過 30 美元的 Orders,並依運送日期排序結果 (從最近的運送日期開始):

Dim selectedOrders = From o In context.Orders _
        Where (o.Freight > 30) _
        Order By o.ShippedDate Descending _
        Select o
var selectedOrders = from o in context.Orders
                     where o.Freight > 30
                     orderby o.ShippedDate descending 
                     select o;

此 LINQ 查詢會轉譯為下列查詢 URI,其會針對 Northwind 架構的快速入門資料服務執行:

https://localhost:12345/Northwind.svc/Orders?Orderby=ShippedDate&?filter=Freight gt 30

如需 LINQ 的一般詳細資訊,請參閱Language-Integrated Query (LINQ)

LINQ 可讓您同時使用語言專屬的宣告式查詢語法 (如以上範例所示),以及所謂標準查詢運算子的一組查詢方法來撰寫查詢。相當於以上範例的查詢僅能使用以方法為基礎的語法撰寫,如以下範例所示:

Dim selectedOrders = context.Orders _
                     .Where(Function(o) o.Freight.Value > 30) _
                     .OrderByDescending(Function(o) o.ShippedDate)
var selectedOrders = context.Orders
                    .Where(o => o.Freight > 30)
                    .OrderByDescending(o => o.ShippedDate);

WCF Data Services 用戶端可以將這兩種撰寫查詢轉譯成查詢 URI,而且您可以藉由將查詢方法附加到查詢運算式,來擴充 LINQ 查詢。當您藉由將方法語法附加到查詢運算式或 DataServiceQuery 來撰寫 LINQ 查詢時,會以呼叫方法的順序,將運算加入至查詢 URI。這相當於呼叫 AddQueryOption 方法,將每個查詢選項加入至查詢 URI。

執行 LINQ 查詢

FirstSingle 之類的特定 LINQ 查詢方法附加至查詢時,會執行該查詢。以隱含的方式列舉結果時 (例如在 foreach 執行迴圈期間),或將查詢指派到 List 集合時,也會執行查詢。如需詳細資訊,請參閱查詢資料服務 (WCF Data Services)

用戶端會以兩個部分執行 LINQ 查詢。如果可能,查詢中的 LINQ 運算式會先在用戶端上進行評估,然後產生 URI 架構的查詢,並將其傳送至資料服務,以便針對服務中的資料進行評估。如需詳細資訊,請參閱查詢資料服務 (WCF Data Services) 中的Client versus Server Execution一節。

在與 OData 相容的查詢 URI 中無法轉譯 LINQ 查詢時,如果嘗試執行,就會引發例外狀況。如需詳細資訊,請參閱查詢資料服務 (WCF Data Services)

LINQ 查詢範例

以下各節中的範例會示範可以針對 OData 服務執行的 LINQ 查詢種類。

篩選

本節中的 LINQ 查詢範例會篩選服務所傳回之摘要中的資料。

下列範例是相當於篩選傳回之 Orders 實體的查詢,因此只會傳回運費成本超過 30 美元的訂單:

  • 使用 LINQ 查詢語法:

    Dim filteredOrders = From o In context.Orders
                            Where o.Freight.Value > 30
                            Select o
    
    var filteredOrders = from o in context.Orders
                            where o.Freight > 30
                            select o;
    
  • 使用 LINQ 查詢方法:

    Dim filteredOrders = context.Orders.Where(Function(o) o.Freight.Value > 0)
    
    var filteredOrders = context.Orders
        .Where(o => o.Freight > 30);
    
  • URI 查詢字串 $filter 選項:

    ' Define a query for orders with a Freight value greater than 30.
    Dim filteredOrders _
                = context.Orders.AddQueryOption("$filter", "Freight gt 30M")
    
    // Define a query for orders with a Freight value greater than 30.
    var filteredOrders
        = context.Orders.AddQueryOption("$filter", "Freight gt 30M");
    

先前的所有範例都會轉譯為查詢 URI:https://localhost:12345/northwind.svc/Orders()?$filter=Freight gt 30M

排序

下列範例示範相當於依公司名稱和郵遞區號,以遞減的方式排序傳回之資料的查詢:

  • 使用 LINQ 查詢語法:

    Dim sortedCustomers = From c In context.Customers
                                 Order By c.CompanyName Ascending,
                                 c.PostalCode Descending
                                 Select c
    
    var sortedCustomers = from c in context.Customers
                         orderby c.CompanyName ascending, 
                         c.PostalCode descending
                         select c;
    
  • 使用 LINQ 查詢方法:

    Dim sortedCustomers = context.Customers.OrderBy(Function(c) c.CompanyName) _
    .ThenByDescending(Function(c) c.PostalCode)
    
    var sortedCustomers = context.Customers.OrderBy(c => c.CompanyName)
        .ThenByDescending(c => c.PostalCode);
    
  • URI 查詢字串 $orderby 選項:

    Dim sortedCustomers = context.Customers _
                          .AddQueryOption("$orderby", "CompanyName, PostalCode desc")
    
    var sortedCustomers = context.Customers
        .AddQueryOption("$orderby", "CompanyName, PostalCode desc");
    

先前的所有範例都會轉譯為查詢 URI:https://localhost:12345/northwind.svc/Customers()?$orderby=CompanyName,PostalCode desc

投影

下列範例示範相當於將傳回的資料投影成較窄之 CustomerAddress 類型的查詢:

  • 使用 LINQ 查詢語法:

    Dim projectedQuery = From c In context.Customers
                         Select New CustomerAddress With
                        {
                            .CustomerID = c.CustomerID,
                            .Address = c.Address,
                            .City = c.City,
                            .Region = c.Region,
                            .PostalCode = c.PostalCode,
                            .Country = c.Country
                        }
    
    var projectedQuery = from c in context.Customers
                select new CustomerAddress
                {
                    CustomerID = c.CustomerID,
                    Address = c.Address,
                    City = c.City,
                    Region = c.Region,
                    PostalCode = c.PostalCode,
                    Country = c.Country
                };
    
  • 使用 LINQ 查詢方法:

    Dim projectedQuery = context.Customers.Where(Function(c) c.Country = "Germany") _
                .Select(Function(c) New CustomerAddress With
                {
                    .CustomerID = c.CustomerID,
                    .Address = c.Address,
                    .City = c.City,
                    .Region = c.Region,
                    .PostalCode = c.PostalCode,
                    .Country = c.Country
                })
    
    var projectedQuery = context.Customers.Where(c => c.Country == "Germany")
        .Select(c => new CustomerAddress
        {
            CustomerID = c.CustomerID, 
            Address = c.Address,
            City = c.City,
            Region = c.Region,
            PostalCode = c.PostalCode,
            Country = c.Country});                   
    
Ee622463.note(zh-tw,VS.100).gif注意:
您無法使用 AddQueryOption 方法,將 $select 查詢選項加入至查詢 URI。建議您使用 LINQ Select 方法,讓用戶端在要求 URI 中產生 $select 查詢選項。

先前的兩個範例都會轉譯為查詢 URI:"https://localhost:12345/northwind.svc/Customers()?$filter=Country eq 'GerGerm'&$select=CustomerID,Address,City,Region,PostalCode,Country"

用戶端分頁

下列範例示範相當於要求包含 25 個訂單,並略過前 50 個訂單之排序實體頁面的查詢:

  • 將查詢方法套用至 LINQ 查詢:

    Dim pagedOrders = (From o In context.Orders
                       Order By o.OrderDate Descending
                       Select o) _
                   .Skip(50).Take(25)
    
    var pagedOrders = (from o in context.Orders
                          orderby o.OrderDate descending
                         select o).Skip(50).Take(25);
    
  • URI 查詢字串 $skip$top 選項:

    Dim pagedOrders = context.Orders _
                      .AddQueryOption("$orderby", "OrderDate desc") _
                      .AddQueryOption("$skip", 50) _
                      .AddQueryOption("$top", 25) _
    
    var pagedOrders = context.Orders
        .AddQueryOption("$orderby", "OrderDate desc")
        .AddQueryOption("$skip", 50)
        .AddQueryOption("$top", 25);
    

先前的兩個範例都會轉譯為查詢 URI:https://localhost:12345/northwind.svc/Orders()?$orderby=OrderDate desc&$skip=50&$top=25

展開

當您查詢 OData 資料服務時,可以要求與查詢做為目標之實體相關的實體包含傳回的摘要。系統會針對 LINQ 查詢做為目標的實體集,在 DataServiceQuery 上呼叫 Expand 方法,並將相關的實體集名稱當做 path 參數提供。如需詳細資訊,請參閱載入延後的內容 (WCF 資料服務)

下列範例示範相當於在查詢中使用 Expand 方法的方式:

  • 使用 LINQ 查詢語法:

    Dim ordersQuery = From o In context.Orders.Expand("Order_Details")
                         Where o.CustomerID = "ALFKI"
                         Select o
    
    var ordersQuery = from o in context.Orders.Expand("Order_Details")
                         where o.CustomerID == "ALFKI"
                         select o;
    
  • 使用 LINQ 查詢方法:

    Dim ordersQuery = context.Orders.Expand("Order_Details") _
                              .Where(Function(o) o.CustomerID = "ALFKI")
    
    var ordersQuery = context.Orders.Expand("Order_Details")
                      .Where(o => o.CustomerID == "ALFKI");
    

先前的兩個範例都會轉譯為查詢 URI:https://localhost:12345/northwind.svc/Orders()?$filter=CustomerID eq 'ALFKI'&$expand=Order_Details

不支援的 LINQ 方法

下表包含不支援,而且不得包含在針對 OData 服務執行之查詢中的 LINQ 方法類別:

運算類型  不支援的方法

設定運算子

針對 DataServiceQuery,不支援所有設定運算子,其中包括:

排序運算子

針對 DataServiceQuery,不支援需要 IComparer 的下列排序運算子:

投影及篩選運算子

針對 DataServiceQuery,不支援接受位置引數的下列投影及篩選運算子:

群組運算子

針對 DataServiceQuery,不支援所有群組運算子,包括:

群組運算必須在用戶端上執行。

彙總運算子

針對 DataServiceQuery,不支援所有彙總運算,包括:

彙總運算必須在用戶端上執行,或由服務作業封裝。

分頁運算子

針對 DataServiceQuery,不支援下列分頁運算子:

Ee622463.note(zh-tw,VS.100).gif注意:
在空序列上執行的分頁運算子會傳回 null。

其他運算子

針對 DataServiceQuery,不支援下列其他運算子:

  1. Empty

  2. Range

  3. Repeat

  4. ToDictionary

  5. ToLookup

支援的運算式函式

下列 Common Language Runtime (CLR) 方法和屬性可以在查詢運算式中轉譯,以便加入 OData 服務的要求 URI,因此受到支援:

String 成員 支援的 OData 函式

Concat

string concat(string p0, string p1)

Contains

bool substringof(string p0, string p1)

EndsWith

bool endswith(string p0, string p1)

IndexOf

int indexof(string p0, string p1)

Length

int length(string p0)

Replace

string replace(string p0, string find, string replace)

Substring

string substring(string p0, int pos)

Substring

string substring(string p0, int pos, int length)

ToLower

string tolower(string p0)

ToUpper

string toupper(string p0)

Trim

string trim(string p0)

DateTime 成員1 支援的 OData 函式

Day

int day(DateTime p0)

Hour

int hour(DateTime p0)

Minute

int minute(DateTime p0)

Month

int month(DateTime p0)

Second

int second(DateTime p0)

Year

int year(DateTime p0)

1相等的 Microsoft.VisualBasic.DateAndTime 日期和時間屬性,以及 Visual Basic 中的 DatePart 方法也受到支援。

Math 成員 支援的 OData 函式

Ceiling

decimal ceiling(decimal p0)

Ceiling

double ceiling(double p0)

Floor

decimal floor(decimal p0)

Floor

double floor(double p0)

Round

decimal round(decimal p0)

Round

double round(double p0)

Expression 成員 支援的 OData 函式

TypeIs

bool isof(type p0)

用戶端可能也可以評估用戶端上的其他 CLR 函式。系統會針對無法在用戶端上評估,而且無法轉譯為有效要求 URI 以便在伺服器上進行評估的所有運算式,引發 NotSupportedException

另請參閱

概念

查詢資料服務 (WCF Data Services)
查詢投影 (WCF 資料服務)
物件具體化 (WCF Data Services)

其他資源

OData:URI 慣例