2014-10-16 80 views
2

我有一個產品odata控制器和一個產品類別odata控制器。
它們都使用實體框架實體並且具有用於odata擴展的導航方法。
這兩個展開工作正常。
現在我在實體框架中添加了一個存儲過程來處理從數據庫返回的數據,並仍然返回一個「Product」記錄。
我將實體存儲過程函數返回類型設置爲「Product」,並在Product odata控制器中創建一個新函數來調用實體函數並返回「Product」。
我可以從url調用該函數,並且它正確地返回一個Product實體/ json。
現在我需要調用網址上的展開來獲得「產品類別」實體,但是失敗。Webapi odata使用實體框架功能展開

我看過這篇文章,但這是基於非實體模型。我的實體都是正確的,運行良好。
http://beyondtheduck.com/projecting-and-the-odata-expand-query-option-possible-at-last-kinda/

回答

1

這是我用來解決問題的代碼。
絕不是「正確」的代碼。
例如:如果在包含ODataActionParameters的Action上使用,則ODataQueryOptions.Top/Skip將爲空。
ODataActionParameters將包含Top/Skip作爲參數嗎?很奇怪。
因此,我希望Microsoft或其他人能夠在未來解決此問題。

控制器:

[HttpPost] 
[EnableQuery] 
public PageResult<SomeObject> SomeFunction(ODataQueryOptions<SomeObject> options, ODataActionParameters parameters) 
{ 
    // Get the paging settings from ODataActionParameters since they are not shown on the ODataQueryOptions. Maybe there will be some fix for this in the future. 
    int pageSize = (int)parameters["pageSize"]; 
    int take = (int)parameters["take"]; 
    int skip = (int)parameters["skip"]; 
    int page = (int)parameters["page"]; 

    // Apply page size settings 
    ODataQuerySettings settings = new ODataQuerySettings(); 

    // Create a temp result set to hold the results from the stored procedure 
    var tempResults = db.SomeStoredProc().ToList(); // ToList is required to get the "real" total count before paging 

    // Apply the query options. For now this is only needed to get the correct count since the options does not seem to contain the TOP/SKIP when using OData parameters. 
    IQueryable results = options.ApplyTo(tempResults.AsQueryable(), settings); 

    // This was needed for custom paging. EXAMPLE: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options 
    return new PageResult<SomeObject>(tempResults.Skip(skip).Take(take), 
          Request.ODataProperties().NextLink, 
          Request.ODataProperties().TotalCount); 
} 

然後WebApiConfig:

var SomeFunction = builder.Entity<SomeObject>().Collection.Action("SomeFunction"); 
SomeFunction.Parameter<int>("take"); 
SomeFunction.Parameter<int>("skip"); 
SomeFunction.Parameter<int>("page"); 
SomeFunction.Parameter<int>("pageSize"); 
SomeFunction.ReturnsCollectionFromEntitySet<SomeObject>("SomeObjects"); 
1

根據你的描述,似乎你需要將[EnableQuery]屬性添加到控制方法的存儲過程。

下實現對我的作品:

WebApiConfig.cs

builder.EntityType<Product>().Function("SomeFunction").ReturnsFromEntitySet<Product>("Products"); 

ProductsController.cs

[HttpGet] 
[EnableQuery] 
public IHttpActionResult SomeFunction() 
{ 
    return Ok(products.FirstOrDefault(c => c.ID == 1)); 
} 

在瀏覽器:

GET http://localhost:54017/Products(1)/Default.SomeFunction()?$expand=Categories 

{ 
    @odata.context: "http://localhost:54017/$metadata#Products", 
    value: [ 
    { 
     ID: 1, 
     Name: "Some", 
     Categories: [ 
     { 
      ID: 1, 
      Name: "Some" 
     } 
     ] 
    } 
    ] 
} 

更新於2014年10月22日:

我修改你連接並在下方附加下來的代碼。你會嘗試,如果它的工作?

[HttpPost] 
[EnableQuery(PageSize=10)] 
public IHttpActionResult SomeFunction() 
{ 
    var results = db.SomeStoredProc().ToList(); 
    return Ok(results); 
} 

類似的功能在我的測試工作。這可以起作用的原因是Web API OData自動爲您處理$skip,$top和分頁。你不必擔心將它們應用於你的結果。客戶端的查詢選項將應用於您返回的整個集合。

+0

你是在說, 「EnableQuery」 正確確實與拓展工作。我應該更好地解釋我的問題。在使用StoredProcedure和分頁時,「EnableQuery」似乎不起作用。就像「PageResult」一樣...... – goroth 2014-10-20 19:14:47

+0

@goroth爲什麼要按照您所描述的那樣使用PageResult,返回值將是單個「產品」記錄。但是,如果您要返回產品集合以及分頁,則可以使用「[EnableQuery(PageSize = 10)]」的返回類型作爲「IQueryable 」來執行此操作。 – 2014-10-21 11:21:43

+0

關鍵詞是「StoredProcedure」。由於存儲過程將始終返回所有記錄,因此我認爲必須先使用「PageResults」來獲取「總計數」,然後在返回結果中設置「take/skip」。 – goroth 2014-10-21 12:48:27