C# Webapi odata使用实体框架函数进行扩展
我有一个产品odata控制器和一个产品类别odata控制器。C# Webapi odata使用实体框架函数进行扩展,c#,entity-framework,asp.net-web-api,odata,C#,Entity Framework,Asp.net Web Api,Odata,我有一个产品odata控制器和一个产品类别odata控制器。 它们都使用实体框架实体,并具有用于odata扩展的导航方法。 两者的扩展都很好。 现在,我在entity framework中添加了一个存储过程来处理从数据库返回的数据,并且仍然返回一个“产品”记录。 我将实体存储过程函数返回类型设置为“Product”,并在Product odata控制器中创建了一个新函数来调用实体函数并返回“Product”。 我可以从url调用函数,这将正确返回产品实体/json。 现在我需要调用url上的扩展
它们都使用实体框架实体,并具有用于odata扩展的导航方法。
两者的扩展都很好。
现在,我在entity framework中添加了一个存储过程来处理从数据库返回的数据,并且仍然返回一个“产品”记录。
我将实体存储过程函数返回类型设置为“Product”,并在Product odata控制器中创建了一个新函数来调用实体函数并返回“Product”。
我可以从url调用函数,这将正确返回产品实体/json。
现在我需要调用url上的扩展来获取“ProductCategory”实体,但这失败了 我看过这篇文章,但这是基于非实体模型的。我的实体都是正确的,运行良好。
根据您的描述,似乎需要将
[EnableQuery]
属性添加到存储过程的控制器方法中
以下实施对我来说很有效:
在WebApiConfig.cs
中:
builder.EntityType<Product>().Function("SomeFunction").ReturnsFromEntitySet<Product>("Products");
[HttpGet]
[EnableQuery]
public IHttpActionResult SomeFunction()
{
return Ok(products.FirstOrDefault(c => c.ID == 1));
}
在浏览器中:
GET http://localhost:54017/Products(1)/Default.SomeFunction()?$expand=Categories
给予
于2014年10月22日更新:
我已经修改了您附加的代码,并将其附加到下面。如果行得通,你会试试吗
[HttpPost]
[EnableQuery(PageSize=10)]
public IHttpActionResult SomeFunction()
{
var results = db.SomeStoredProc().ToList();
return Ok(results);
}
类似的功能在我的测试中起作用。这样做的原因是Web API OData会自动为您处理
$skip
、$top
和分页。您不必担心将它们应用到结果中。客户端的查询选项将应用于您返回的整个集合 这是我用来解决这个问题的代码。绝对不是“正确”的代码。
例如:ODataQueryOptions.Top/Skip如果用于包含ODataActionParameters的操作,则将为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);
}
[HttpPost]
[启用查询]
公共页面结果SomeFunction(ODataQueryOptions选项、ODataActionParameters参数)
{
//从ODataActionParameters获取分页设置,因为它们没有显示在ODataQueryOptions上。也许将来会有一些解决方案。
int pageSize=(int)参数[“pageSize”];
int take=(int)参数[“take”];
int skip=(int)参数[“skip”];
int page=(int)参数[“page”];
//应用页面大小设置
ODataQuerySettings设置=新的ODataQuerySettings();
//创建临时结果集以保存存储过程的结果
var tempResults=db.SomeStoredProc().ToList();//需要ToList才能在分页之前获取“实际”总计数
//应用查询选项。目前,这仅用于获得正确的计数,因为在使用OData参数时,选项似乎不包含TOP/SKIP。
IQueryable results=options.ApplyTo(tempResults.AsQueryable(),settings);
//这是自定义分页所必需的。示例:http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options
返回新的PageResult(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");
var SomeFunction=builder.Entity().Collection.Action(“SomeFunction”);
参数(“take”);
参数(“跳过”);
参数(“页面”);
参数(“页面大小”);
ReturnsCollectionFromEntitySet(“SomeObjects”);
您是正确的,因为“EnableQuery”确实适用于扩展。我应该更好地解释我的问题。在使用StoredProcess和分页时,“EnableQuery”似乎不起作用。比如“PageResult”…@goroth为什么要使用PageResult,因为您描述了返回值将是单个“产品”记录。但是,如果您将产品集合与分页一起返回,则可以使用“[EnableQuery(PageSize=10)]”将返回类型设置为“IQueryable”。关键字是“StoredProcess”。由于存储过程总是返回所有记录,我想我必须使用“PageResults”首先获取“total count”,然后在返回结果上设置“take/skip”。
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");