2014-10-16 78 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