简体   繁体   English

从 .NET OData 4 客户端调用嵌套 Expand() 的正确方法

[英]Proper way to call nested Expand() from .NET OData 4 Client

Problem问题

In an OData 4 service on Web API, what is the proper way to call nested $expand from a .NET client?在 Web API 上的 OData 4 服务中,从 .NET 客户端调用嵌套 $expand 的正确方法是什么? We are using the OData Client Generator .我们正在使用OData 客户端生成器 Back in the prior WCF Data Services with OData 3 service we could call .Expand("Customers/Orders") .回到带有 OData 3 服务的先前 WCF 数据服务中,我们可以调用.Expand("Customers/Orders") In Web API with OData 4 we can no longer do so and receive the following should you attempt .Expand("Customers/Orders") :在带有 OData 4 的 Web API 中,如果您尝试.Expand("Customers/Orders")我们将无法再这样做并收到以下信息:

The query specified in the URI is not valid. URI 中指定的查询无效。 Found a path traversing multiple navigation >properties.找到了一条遍历多个导航 > 属性的路径。 Please rephrase the query such that each expand path contains only type >segments and navigation properties.请重新表述查询,使每个展开路径仅包含类型 > 段和导航属性。

Workaround解决方法

We are able to work around this by calling expand like so: .Expand("Customers($expand=Orders)") .我们可以通过像这样调用 expand 来解决这个问题: .Expand("Customers($expand=Orders)") In non-nested $expand scenarios, I like the lambda support like so .Expand(d => d.Customers) .在非嵌套的 $expand 场景中,我喜欢像这样的 lambda 支持.Expand(d => d.Customers) Is there a proper way in .NET OData 4 client to call nested expands without the unfortunate magic string of .Expand("Customers($expand=Orders)") ?在 .NET OData 4 客户端中是否有正确的方法来调用嵌套扩展而没有.Expand("Customers($expand=Orders)")的不幸魔法字符串? If not, is there a cleaner string pattern like "Customers/Orders" that would work?如果没有,是否有像“客户/订单”这样的更清晰的字符串模式可以工作? Thanks.谢谢。

The request that you want to send is:您要发送的请求是:

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

right?对?

According to the OData protocol:根据 OData 协议:

To request related entities according to a particular relationship, the client issues a GET request to the source entity ’s request URL, followed by a forward slash and the name of the navigation property representing the relationship.要根据特定关系请求相关实体,客户端向源实体的请求 URL 发出 GET 请求,后跟正斜杠和表示关系的导航属性的名称。

So such request is not supported as the "Customers" before "/Orders" is the name of an entity set instead of a single entity.因此,不支持此类请求,因为“/Orders”之前的“Customers”是实体集的名称,而不是单个实体。 You can only write nested expanding like:您只能编写嵌套扩展,例如:

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

Which corresponds to the following code snippets using OData V4 Code Generator:这对应于以下使用 OData V4 代码生成器的代码片段:

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

And you need to iterate through all the customers to get all their orders.并且您需要遍历所有客户以获取他们的所有订单。

A little extension for that :对此的一点扩展:

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

Now you have intellisense and type checking现在你有了智能感知和类型检查

Example :例子 :

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

In OData v4, it is not valid to expand multi levels, such as what you mentioned in the question: .Expand("Customers/Orders").在 OData v4 中,扩展多级是无效的,例如您在问题中提到的:.Expand("Customers/Orders")。 I dont think the client will support such API.我不认为客户端会支持这样的 API。 Here is what in the ABNF http://docs.oasis-open.org/odata/odata/v4.0/os/abnf/odata-abnf-construction-rules.txt :这是 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 ]

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

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