【问题标题】:Webapi odata expand with entity framework functionsWebapi odata 扩展实体框架功能
【发布时间】:2014-12-11 21:41:40
【问题描述】:

我有一个 Product odata 控制器和一个 Product Category odata 控制器。
它们都使用实体框架实体,并具有用于 odata 扩展的导航方法。
两者的展开都运行良好。
现在我在实体框架中添加了一个存储过程来操作从数据库返回的数据,并且仍然返回一个“产品”记录。
我将实体存储过程函数返回类型设置为“Product”,并在 Product odata 控制器中创建了一个新函数来调用实体函数并返回“Product”。
我可以从 url 调用函数,这将正确返回 Product 实体/json。
现在我需要调用 url 上的扩展来获取“产品类别”实体,但这失败了。

我查看了这篇文章,但这是基于非实体模型的。我的实体都正确且运行良好。
http://beyondtheduck.com/projecting-and-the-odata-expand-query-option-possible-at-last-kinda/

【问题讨论】:

    标签: c# entity-framework asp.net-web-api odata


    【解决方案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 和分页。您无需担心将它们应用于您的结果。来自客户端的查询选项将应用于您返回的整个集合。

    【讨论】:

    • 您是正确的,因为“EnableQuery”确实适用于展开。我应该更好地解释我的问题。将 StoredProcedure 与分页一起使用时,“EnableQuery”似乎不起作用。像“PageResult”...
    • @goroth 你为什么要使用 PageResult 正如你所描述的返回值将是一个单一的“产品”记录。但是,如果您在分页的同时返回产品集合,则可以将返回类型设置为“IQueryable”,因为使用“[EnableQuery(PageSize = 10)]”来执行此操作。
    • 关键字是“StoredProcedure”。由于存储过程总是会返回所有记录,我想我必须先使用“PageResults”来获取“总计数”,然后在返回结果上设置“采取/跳过”。
    【解决方案2】:

    这是我用来解决问题的代码。
    绝不是“正确”的代码。
    例如:如果在包含 ODataActionParameters 的操作上使用 ODataQueryOptions.Top / Skip 将为 null。
    ODataActionParameters 会包含 Top/Skip 作为参数吗?很奇怪。
    所以我添加了两者,希望微软或其他人将来可以解决这个问题。

    控制器:

    [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");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-02
      • 1970-01-01
      • 2016-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多