OData V4:是否可以只从父实体中选择字段(即导航属性)?

时间:2018-03-12 21:45:53

标签: select odata expand odata-v4

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)?$扩大=产品($扩大=类别($选择类别名称=))

我最接近的是从每个级别中选择一个字段,在我们的代码中引入了很多复杂性,并且很难确保所有查询(未来和现有)都遵守此规则。

3 个答案:

答案 0 :(得分:1)

其语法为:

http://services.odata.org/V4/Northwind/Northwind.svc/Order_Details(OrderID=10248,ProductID=11)/Product?$expand=Category($select=CategoryName)

关键是要从订单导航到父产品资源的路径:

~/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)

<块引用>

我能得到的最接近的是从每个级别中选择一个字段, 给我们的代码引入了很多复杂性 难以确保所有查询(未来的和现有的)都遵守 这条规则。

看起来像这样:

http://services.odata.org/V4/Northwind/Northwind.svc/Order_Details(OrderID=10248,ProductID=11)?$expand=Product($select=Category;$expand=Category($select=CategoryName))&$select=Product

这里肯定会增加一些复杂性,但在我的情况下这是可以接受的。