简体   繁体   English

Webapi odata扩展了实体框架功能

[英]Webapi odata expand with entity framework functions

I have a Product odata controller and a Product Category odata controller. 我有一个产品odata控制器和一个产品类别odata控制器。
They are both using entity framework entities and have navigation methods used for odata expand. 它们都使用实体框架实体,并具有用于odata扩展的导航方法。
The expand for both is working fine. 两者的扩展工作正常。
Now I added a stored procedure in entity framework to manipulate the data returned from the database and still return a "Product" record. 现在我在实体框架中添加了一个存储过程来操作从数据库返回的数据,并仍然返回“Product”记录。
I set the entity stored procedure function return type to "Product" and created a new function in the Product odata controller to call the entity function and return "Product". 我将实体存储过程函数返回类型设置为“Product”,并在Product odata控制器中创建一个新函数来调用实体函数并返回“Product”。
I can call the function from a url and this is returning a Product entity / json correctly. 我可以从一个url调用该函数,这正确地返回一个Product实体/ json。
Now I need to call the expand on the url to get the "Product Category" entity but this fails. 现在我需要调用url上的expand来获取“Product Category”实体,但这会失败。

I looked into this article but this is based on non-entity models. 我查看了这篇文章,但这是基于非实体模型。 My entities are all correct and functioning fine. 我的实体都是正确的,运作正常。
http://beyondtheduck.com/projecting-and-the-odata-expand-query-option-possible-at-last-kinda/ http://beyondtheduck.com/projecting-and-the-odata-expand-query-option-possible-at-last-kinda/

According to your description, it seems that you need to add the [EnableQuery] attribute to the controller method for the stored procedure. 根据您的描述,您似乎需要将[EnableQuery]属性添加到存储过程的控制器方法中。

The following implementation works for me: 以下实现对我有用:

In WebApiConfig.cs : WebApiConfig.cs

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

In ProductsController.cs : ProductsController.cs

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

In browser: 在浏览器中:

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

gives

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

Updated on 10/22/2014: 2014年10月22日更新:

I've modified the code you attached and attach it down below. 我修改了你附加的代码并将其附在下面。 Would you try if it works? 你会尝试它是否有效?

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

Similar function worked in my tests. 类似的功能在我的测试中有效。 The reason that this would work is that Web API OData handles the $skip , $top , and paging for you automatically. 这可行的原因是Web API OData会自动为您处理$skip$top和paging。 You don't need to worry about applying them to your result. 您无需担心将它们应用于您的结果。 The query options from the client will be applied to the whole set you return. 来自客户端的查询选项将应用于您返回的整个集合。

Here is the code I used to fix the problem. 这是我用来解决问题的代码。
By no means is it "correct" code. 绝不是“正确”的代码。
For example: ODataQueryOptions.Top / Skip will be null if used on an Action that contains ODataActionParameters. 例如:如果在包含ODataActionParameters的Action上使用,则ODataQueryOptions.Top / Skip将为null。
ODataActionParameters will contain the Top / Skip as a parameter? ODataActionParameters将包含Top / Skip作为参数? Very odd. 很奇怪。
So I added both in the hopes that Microsoft or someone else can fix this issue in the future. 因此,我希望微软或其他人可以在将来修复此问题。

Controller: 控制器:

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

Then WebApiConfig: 然后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");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM