10

问题

在 Web API 上的 OData 4 服务中,从 .NET 客户端调用嵌套 $expand 的正确方法是什么?我们正在使用OData 客户端生成器。回到之前的 WCF 数据服务,我们可以调用 OData 3 服务.Expand("Customers/Orders")。在带有 OData 4 的 Web API 中,如果您尝试,我们将无法再这样做并收到以下信息.Expand("Customers/Orders")

URI 中指定的查询无效。找到了一个遍历多个导航 > 属性的路径。请改写查询,使每个展开路径仅包含类型 >segments 和导航属性。

解决方法

我们可以通过调用 expand 来解决这个问题.Expand("Customers($expand=Orders)"):在非嵌套的 $expand 场景中,我喜欢这样的 lambda 支持.Expand(d => d.Customers)。.NET OData 4 客户端中是否有适当的方法来调用嵌套扩展而没有不幸的魔术字符串.Expand("Customers($expand=Orders)")?如果没有,是否有像“客户/订单”这样更简洁的字符串模式可以使用?谢谢。

4

3 回答 3

3

您要发送的请求是:

GET http://host/service/Customers/Orders

对?

根据 OData 协议:

为了根据特定关系请求相关实体,客户端向源实体的请求 URL 发出 GET 请求,后跟正斜杠和表示关系的导航属性的名称。

因此,不支持此类请求,因为“/Orders”之前的“客户”是实体集的名称,而不是单个实体的名称。您只能编写嵌套扩展,例如:

GET http://host/service/Customers(1)/Orders

对应于使用 OData V4 代码生成器的以下代码片段:

var orders = context.Customers.ByKey(new Dictionary<string, object>() { { "ID", 1 } }).Orders.Execute();

您需要遍历所有客户以获取他们的所有订单。

于 2014-08-12T02:54:02.187 回答
2

对此的一点扩展:

        public static DataServiceQuery<TSource> Expand<TSource,TNavigation,TExpand>(this DataServiceQuery<TSource> dataServiceQuery, Expression<Func<TSource, DataServiceCollection<TNavigation>>> expression,  Expression<Func<TNavigation,TExpand>> navigation)
    {
        var expressionName = (expression.Body as System.Linq.Expressions.MemberExpression).Member.Name;
        var navigationName = (navigation.Body as System.Linq.Expressions.MemberExpression).Member.Name;


        return dataServiceQuery.Expand($"{expressionName}($expand={navigationName})");
    }

现在你有了智能感知和类型检查

例子 :

db.Container.Expand(c=> c.Customers, customer => customer.Orders)

于 2020-05-05T09:38:50.000 回答
1

在 OData v4 中,扩展多个级别是无效的,例如您在问题中提到的内容:.Expand("Customers/Orders")。我认为客户端不会支持这样的 API。这是 ABNF http://docs.oasis-open.org/odata/odata/v4.0/os/abnf/odata-abnf-construction-rules.txt中的内容:

expand            = '$expand' EQ expandItem *( COMMA expandItem )
expandItem        = STAR [ ref / OPEN levels CLOSE ]
                  / expandPath
                    [ ref   [ OPEN expandRefOption   *( SEMI expandRefOption   ) CLOSE ]
                    / count [ OPEN expandCountOption *( SEMI expandCountOption ) CLOSE ]
                    /         OPEN expandOption      *( SEMI expandOption      ) CLOSE 
                    ]
expandPath        = [ qualifiedEntityTypeName "/" ] 
                    *( ( complexProperty / complexColProperty ) "/" [ qualifiedComplexTypeName "/" ] )
                    navigationProperty 
                    [ "/" qualifiedEntityTypeName ]
于 2014-08-12T05:06:50.883 回答