我使用的是OData v4,模型是用我们的。net Web API的EdmModel Builder配置的。
我有两个模型定义如下:
public class Customer
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
}
public class Order
{
public int OrderId { get; set; }
public string Category { get; set; }
public Customer OrderCustomer { get; set;}
}
这些模型有相应的控制器,注册如下:
builder.EntitySet<Customer>("Customers")
.EntityType
.HasKey(x => x.CustomerId);
builder.EntitySet<Order>("Orders")
.EntityType
.HasKey(x => x.OrderId)
.Expand(
maxDepth: 2,
expandType: SelectExpandType.Automatic,
properties: nameof(Order.OrderCustomer));
我能够使OData请求这两个端点如下:/Customers/{Id}
和/Orders/{Id}
.
我期望当我查询Orders
时,嵌套的EntitySetCustomers
将自动扩展,因为我已经在Order
EntitySet上设置了expandType: SelectExpandType.Automatic
。然而,我不能让CustomerOrder
属性在Customer
上自动展开,我必须用一个扩展参数调用请求:
/Orders/{Id}?$expand=OrderCustomer
.
我认为这是因为Customer
和Order
都注册为EntitySets,所以OData希望在它们嵌套时提供扩展参数。是否有一种方法可以让OrderCustomer
属性自动扩展(即不需要提供扩展参数)?我对OData/Edm模型的理解是相当初级的,所以任何帮助都是感激的。
您的流畅配置是正确的,对于OData v4,这将适用于集合和项查询。
如果它不能为你工作,有三个可能的问题:
-
您似乎没有为项查询使用OData v4 URL约定,在v4中预期的URL是:
/Orders({Id})
这带来了一个问题,你是如何修改路由器来支持v3语法的,如何实现v3路由有多种不同的方式,所以在这方面所做的更改可能会影响默认扩展和选择的应用方式,或者是否应该应用它。
-
您可能没有在数据查询中包含导航数据。如果没有从数据存储中检索数据,那么它就不会出现在输出记录集中。如果您手动使用
ODataQueryOptions.ApplyTo()
将用户请求应用到您的查询,那么这将不考虑模型上的配置,它将只应用调用者指定的查询选项。 -
调用者可能指定了空
$expand=
,这将取消自动配置。即使原始调用方没有指定任何查询选项,OData api也会运行可能正在操作请求查询字符串的标准或自定义中间件。要验证URL未被篡改,请将其记录在GET
方法处理程序中,并确保没有指定$expand
。- 与前一点一样,如果您希望应用auto配置,则
GET
方法中的ODataQueryOptions
参数应该NOT显示SelectExpand
的任何值。
- 与前一点一样,如果您希望应用auto配置,则
最后,要检查的最后一个地方是您没有覆盖默认的EnableQueryAttribute
。如果您已经实现了自己的EnableQueryAttribute
的自定义实现,那么请确保您仍然调用基本实现来正确地将ODataQueryOptions
和模式默认值应用于底层IQueryable
结果。
除了Chris Schaller提供的答案。
我遇到的另一个问题是由属性上的套管引起的。例如,我在构建器
上启用了camelCasing
builder.EnableLowerCamelCase();
这意味着配置中的Expand
中的命名需要更新以匹配。
.Expand(
maxDepth: 2,
expandType: SelectExpandType.Automatic,
properties: "orderCustomer"); // <-- camelCase
即使在ODataOptions
中启用了EnablePropertyNameCaseInsensitive
,这似乎也是必需的。