2016-09-22 111 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); 
}