在 OData V3 中,我只能从父/祖先实体中选择字段,如下所示: http://services.odata.org/V3/Northwind/Northwind.svc/Order_Details(OrderID=10248,ProductID=11)?& $选择=产品/类别/类别名称&安培; $扩大=产品/分类
该查询仅返回 CategoryName ,它不包含 Order_Details 或 Product 中的任何字段。出于性能原因,此行为对我们的应用程序非常重要。在我们不需要它们时选择所有字段会对查询性能产生重大影响。
在OData V4中似乎没有办法实现相同的目标。等效查询返回 Order_Details 和 Product 中的所有字段 http://services.odata.org/V4/Northwind/Northwind.svc/Order_Details(OrderID=10248,ProductID=11)?$扩大=产品($扩大=类别($选择类别名称=))
我最接近的是从每个级别中选择一个字段,在我们的代码中引入了很多复杂性,并且很难确保所有查询(未来和现有)都遵守此规则。
答案 0 :(得分:1)
其语法为:
关键是要从订单导航到父产品资源的路径:
~/Order_Details(OrderID=10248,ProductID=11)/Product
,然后将扩展应用于该资源。参见4.3 Addressing Entities
这些规则是递归的,因此可以通过另一个实体访问一个实体,通过一个实体访问一个集合,甚至通过一个集合访问一个集合;示例包括但不限于:
- 从单个实体导航到另一个相关实体后(请参阅规则:entityNavigationProperty)
示例14:http://host/service/Products(1)/Supplier
答案 1 :(得分:0)
最简单的解决方案是在数据库服务器上创建具有所需架构的View,然后尝试使用过滤器和列名从此数据源中获取数据。
尤其是在遇到性能问题时。
最好的方法是将该类作为单例注册到您的IoC
public class InternalODataEdmModelBuilder
{
private readonly ODataConventionModelBuilder _oDataConventionModelBuilder = new ODataConventionModelBuilder();
private IEdmModel _edmModel;
public InternalODataEdmModelBuilder()
{
ODataEntitySetsConfigInternal.Register(_oDataConventionModelBuilder);
}
// cache
public IEdmModel GetEdmModel()
{
return _edmModel ?? (_edmModel = _oDataConventionModelBuilder.GetEdmModel());
}
}
internal static class ODataEntitySetsConfigInternal
{
public static void Register(ODataConventionModelBuilder oDataModelBuilder)
{
if (oDataModelBuilder == null)
{
throw new Exception("'ODataConventionModelBuilderWebApi' cannot be null");
}
oDataModelBuilder.EntitySet<YourView>("YourView").EntityType.HasKey(x => x.YourKey);
}
}
然后将这个注册的对象注入您的API控制器中,并从URL构建查询,如下所示:
ODataQueryContext queryContext = new ODataQueryContext(_oDataConventionModel, typeof(YourViewEFType), null);
var option = new ODataQueryOptions(queryContext, Request);
var data = option.ApplyTo(data, new ODataQuerySettings { EnsureStableOrdering = false });
然后将数据映射到您的POCO(向公众展示的API EDM模型)。
希望这会有所帮助。
答案 2 :(得分:0)
我能得到的最接近的是从每个级别中选择一个字段, 给我们的代码引入了很多复杂性 难以确保所有查询(未来的和现有的)都遵守 这条规则。
看起来像这样:
这里肯定会增加一些复杂性,但在我的情况下这是可以接受的。