網上百度“odata 語法”會出來很多結果,其中有一項是比較一致的,那就是odata支持一下幾種語法:
$filter 條件表達式 -- 對應sql語句的where條件查詢,如:/Categories?$filter=name eq 'liumang'
$expand 包含屬性和關係 -- 對應表的外鍵關係,如:/Categories?$expand=Products
$select 查詢字段的列表 -- 對應sql語句select後面的字段,如:/Categories?$select=id,name
$count 查詢數量 -- 根據當前查詢條件返回的總記錄數,如Categories表中有10條記錄,則/Categories?count 或者 /Categories?count=true
(ps:這條我沒有找到具體確切的用法,在AllowedQueryOptions 枚舉中也沒有列出這條選項)
$orderby 排序 -- 對應sql語句order by語句,如:/Categories?$orderby=id,name ,/Categories?$orderby=id,name desc(asc) ,/Categories?$orderby=id desc,name asc
$skip 當前查詢跳過多少條數據,再返回查詢結果,如:/Categories?$orderby=id&$skip=10,如果id是連續的話,那麼返回從id=11之後的所有數據
$top 返回當前查詢的前多少條數據,如/Categories?$top=10
skip 和top 一般是配合一起使用,用來做分頁查詢,如/Categories?$skip=10&$top=10 ,/Categories?$skip=20&$top=10 ,這樣就可以做出一個pagesize 爲10的分頁查詢了
$inlinecount 返回當前查詢條件的所有記錄數,如:/Categories?$inlinecount=allpages ,如果Categories有23條數據,則返回23
$skiptoken 例如遊標或者書籤的一個東西
$metadata 顯示元數據
以上是在網上找到的相關資料,資料很齊全,很多都給出了案列,但是在我實際的使用中,卻只有幾項數據能夠使用,其他的都不適用,我分析原因可能如下 :
1:我做的項目是集成在mvc和api裏面的,而網上的很多例子大都是wcf的案列,我不太清楚是不是這個原因,因爲wcf我只知道皮毛,沒有深入
2:在程序集 System.Web.Http.OData.dll, v4.0.0.0 中有這樣一段註釋:
// // 摘要: // 獲取或設置允許在查詢內部使用的查詢參數。默認值爲所有查詢選項,包括 $filter、$skip、$top、$orderby、$expand、$select、$inlineCount、$format // 和 $skipToken。 // // 返回結果: // 返回 System.Web.Http.OData.Query.AllowedQueryOptions。
public AllowedQueryOptions AllowedQueryOptions { get; set; }
可以看出 AllowedQueryOptions 枚舉和上面列出的還是有一些出入的
3:同樣在程序集 System.Web.Http.OData.dll, v4.0.0.0 中還有這樣一段註釋:
namespace System.Web.Http.OData.Query // 摘要: // 此項定義可用於執行查詢撰寫的複合 OData 查詢選項。此項當前僅支持 $filter、$orderby、$top 和 $skip。 // // 類型參數: // TEntity: [ODataQueryParameterBinding] public class ODataQueryOptions<TEntity> : ODataQueryOptions
可以看出只支持四個選項,這和我在項目中的使用情況是一致的。
ps:讓我疑惑的一點就是,odata 4.0裏面是支持我上面列出的所有查詢選項的,而在api 2.2發佈的時候則是明確表示支持odata 4.0的,我不知道是什麼原因導致我現在的項目中只支持四個選項.
說了這麼多後,回到主題上面來,在項目中其實 $filter、$orderby、$top 和 $skip 四個選項是可以支持90%左右的查詢功能的
其餘10%的功能比如:分頁查詢時必須知道的總記錄數、返回json字符串、外鍵關係等
下面說一下我在網上查到的關於$inlinecount ,$format的解決方法
$format
需要odata支持$format參數只需要一句語句即可
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
//添加下面這句代碼即可支持$format查詢選項,當然需要添加程序集 System.Net.Http.Formatting.dll config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json"); } }
$inlinecount
這個也不需要太多複雜的操作,代碼如下
public class testController : ApiController { testBLL DB = new testBLL(); public PageResult<dict> Get(ODataQueryOptions<dict> options) { int pageSize = 10; ODataQuerySettings settings = new ODataQuerySettings() { PageSize = pageSize }; IQueryable results = options.ApplyTo(DB.FindAll().AsQueryable(), settings); return new PageResult<dict>( results as IEnumerable<dict>, Request.GetNextPageLink(), Request.GetInlineCount()); } }
查詢url : http://localhost:3812/api/test?$skip=20&$inlinecount=allpages
返回格式如下:
int pageSize = options.Top == null ? 10 : options.Top.Value;
在用戶選擇了記錄數時,按照用戶選擇的設置,可以動態的返回下一頁的記錄,但是返回的NextPageLink的值卻爲null,當我去掉top參數時,返回是正常數據
下面是反編譯了System.Web.Http.OData.dll之後的源代碼 ,我想可能在請求發送過來,在設置參數的時候,判斷了過top參數所導致的
public static Uri GetNextPageLink(this HttpRequestMessage request) { object obj2; if (request == null) { throw Error.ArgumentNull("request"); } if (request.get_Properties().TryGetValue("MS_NextPageLink", out obj2)) { return (obj2 as Uri); } return null; }
上面是$format 和 $inlinecount參數的設置方法,$expand 參數我查到相關資料後再整理。