2016-09-22 110 views
0

我是Web API,實體框架和OData的新手。我在另一個論壇上提了一個類似的問題,但沒有得到相關的答覆。Web API OData自定義查詢問題

我們在Salesforce中使用了適用於OData的Web API服務。我們需要公開一個Oracle自定義複雜查詢。

我不知道如何使用自定義查詢,就像我們也想允許odata參數過濾發生? ($ filter,$ top,$ skip等)例如,當使用$ filter時,我想將該過濾器應用於自定義查詢,然後將其發送回數據庫以使其返回結果集。我怎樣才能做到這一點?

我似乎有的問題是,我可以看到參數,因爲他們進來,但他們沒有轉化爲查​​詢被傳遞給甲骨文。它似乎會觸發查詢返回完整的結果集,然後應用參數。這是非常緩慢的,因爲結果集非常大。

我希望2弄清楚2件事 1.我如何使用自定義sql並將odata參數應用於基礎查詢? 2.當使用EF或自定義查詢時,如何將odata參數應用於查詢,以便在將查詢發送到數據庫時(例如查詢中包含$ filter參數)?我不希望完整的結果返回,然後應用過濾器。

任何人都可以給我一些指導如何做到這一點?

private static ODataValidationSettings _validationSettings = new ODataValidationSettings(); 

    //public IHttpActionResult GetName() 
    //{ } 

    // GET: odata/ShareData 
    [ODataRoute("Orders")] 
    [EnableQuery(PageSize = 50)] 
    public IHttpActionResult GetOrders(ODataQueryOptions<Orders> queryOptions) 
    { 
     // validate the query. 
     try 
     { 
      queryOptions.Validate(_validationSettings); 
     } 
     catch (ODataException ex) 
     { 
      return BadRequest(ex.Message); 
     } 

     try 
     { 
      string connectionString = ConfigurationManager.ConnectionStrings["DNATestConnectionString"].ConnectionString; 
      var items = GetDataItems(connectionString); 
      return Ok<IEnumerable<Orders>>(items); 
     } 
     catch (Exception ex) 
     { 
      return StatusCode(HttpStatusCode.InternalServerError); 
     } 
    } 



    #region Load Data Methods 
    private static List<Orders> GetDataItems(string connectionString) 
    { 
     List<Orders> items = new List<Orders>(); 

     using (OracleConnection con = new OracleConnection(connectionString)) 
     { 
      con.Open(); 

      using (OracleCommand cmd = con.CreateCommand()) 
      { 
       cmd.CommandText = "select po_header_id, segment1, vendor_id, vendor_site_id from po_headers_all where vendor_id=4993"; 
       using (OracleDataReader rdr = cmd.ExecuteReader()) 
       { 
        while (rdr.Read()) 
         items.Add(ToOrders(rdr)); 
       } 
      } 
     } 

     return items; 
    } 

    private static Orders ToOrders(OracleDataReader rdr) 
    { 
     Orders data = new Orders(); 

     data.VENDOR_ID = ToInt32(rdr, "VENDOR_ID"); 
     data.VENDOR_SITE_ID = ToInt32(rdr, "VENDOR_SITE_ID"); 
     data.PO_HEADER_ID = ToInt32(rdr, "PO_HEADER_ID"); 
     data.SEGMENT1 = Convert.ToString(rdr["SEGMENT1"]); 

     return data; 
    } 

    private static int ToInt32(OracleDataReader rdr, string name) 
    { 
     int index = rdr.GetOrdinal(name); 
     return rdr.IsDBNull(index) ? 0 : Convert.ToInt32(rdr[index]); 
    } 
    #endregion 

回答

0

我不認爲這是可能的。

  1. 如何使用自定義的SQL和應用的OData參數爲基礎的查詢?

據我所知,你不能。 OData庫的重點在於它需要處理一個IQueryable。通過在您的示例中使用字符串中的自定義SQL,您無法將其與正在傳入的OData參數結合使用。

一種方法是將自定義SQL放在SQL視圖中,然後添加以與添加表相同的方式將EF視圖添加到EF模型 - 它將像表一樣被表示爲DbSet。

然後,您可以得到一個IQueryable來表示數據集,然後應用的OData參數如下:

public IHttpActionResult GetOrders(ODataQueryOptions<OrdersView> queryOptions) 
{ 
    IQueryable<OrdersView> allData = // ... get the DbSet from entity framework... 

    // this will apply the OData query to the data set and only pull the data you want from the database 
    var filteredResults = queryOptions.ApplyTo(allData) as IQueryable<OrdersView>; 


    return Ok<IQueryable<OrdersView>>(filteredResults); 
}