ODATAv4 $expand 在选择显式对象时不起作用
ODATAv4 $expand doesn't work when selecting explicit object
第一个 GET 工作得很好:
http://localhost/webservice/odata/MyStuff?$filter=Id eq 2&$expand=History
它returns一个MyStuff
和History
的数组被展开了。
但是,如果我尝试使用指定的密钥获取 MyStuff,历史导航 属性 不会展开。
http://localhost/webservice/odata/MyStuff(2)?$expand=History
我在启动时已经HttpConfiguration
配置如下
HttpConfiguration
.Filter()
.Expand()
.Select()
.OrderBy()
.MaxTop(null)
.Count();
像这样的问题有多个角度:
- 数据本身
- 用于获取数据的查询
- 提供数据的控制器方法的响应类型
EnableQueryAttribute
配置
您已经证明了数据的存在,因此我们可以对数据本身进行折扣,但其余因素可以通过各种组合实现。
You should update your question to show an example of your controller method that handles the GET by Key request
如果您使用的是像 Entity Framework 这样的 ORM,那么下面的简单控制器显示了一个应该工作的最小实现:
[OData.EnableQuery]
public virtual IHttpActionResult Get([FromODataUri] TKey key, ODataQueryOptions<MyStuff> queryOptions)
{
return SingleResultAction(dbContext.MyStuff.Where(x => x.Id == 2));
}
当然还有很多其他方法,从最低限度的角度来看,使用 SingleResultAction
强制您传递一个查询并验证它只有 returns 一个结果。
只要您的方法返回 IQueryable<>
结果,EnableQueryAttribute
就会自动尝试将 queryOptions
应用于您的查询。
如果您的结果集是手动构造的,或者 NOT 返回为 IQueryable<>
或者不能自动链接,那么您将必须 Apply $expand
手动查询选项。
您可以这样做以仅允许扩展某些导航属性,下一个示例通过积极地将所有 History
记录加载到内存中来准备项目
Not recommended, especially if your navigation property may have many rows and the user will not be expanding very frequently, but it works:
[OData.EnableQuery]
public virtual MyStuff Get([FromODataUri] TKey key, ODataQueryOptions<MyStuff> queryOptions)
{
var item = dbContext.MyStuff.Include(X => x.History).Single(x => x.Id == 2);
return item;
}
这个例子仍然允许 EnableQueryAttribute
到 $expand
甚至 $sort
和 $filter
扩展中的记录,但是,因为整个可用数据已经加载到内存中,EnableQueryAttribute
无法加载其他端点。
in this last example, even though the History
items were loaded into memory, the will only appear in the JSON response if the $expand=History
query option is provided by the caller.
还有很多其他场景,OP 没有提供他们的实现代码,所以这里全是推测。我特意 NOT 演示了如何手动 将 QueryOptions 应用于您的数据查询,您可以这样做,但在您掌握它之前,我鼓励您更接近于最小的实现,我们通过 OData 获得了很多 OOTB,通常足以应付。
第一个 GET 工作得很好:
http://localhost/webservice/odata/MyStuff?$filter=Id eq 2&$expand=History
它returns一个MyStuff
和History
的数组被展开了。
但是,如果我尝试使用指定的密钥获取 MyStuff,历史导航 属性 不会展开。
http://localhost/webservice/odata/MyStuff(2)?$expand=History
我在启动时已经HttpConfiguration
配置如下
HttpConfiguration
.Filter()
.Expand()
.Select()
.OrderBy()
.MaxTop(null)
.Count();
像这样的问题有多个角度:
- 数据本身
- 用于获取数据的查询
- 提供数据的控制器方法的响应类型
EnableQueryAttribute
配置
您已经证明了数据的存在,因此我们可以对数据本身进行折扣,但其余因素可以通过各种组合实现。
You should update your question to show an example of your controller method that handles the GET by Key request
如果您使用的是像 Entity Framework 这样的 ORM,那么下面的简单控制器显示了一个应该工作的最小实现:
[OData.EnableQuery]
public virtual IHttpActionResult Get([FromODataUri] TKey key, ODataQueryOptions<MyStuff> queryOptions)
{
return SingleResultAction(dbContext.MyStuff.Where(x => x.Id == 2));
}
当然还有很多其他方法,从最低限度的角度来看,使用 SingleResultAction
强制您传递一个查询并验证它只有 returns 一个结果。
只要您的方法返回 IQueryable<>
结果,EnableQueryAttribute
就会自动尝试将 queryOptions
应用于您的查询。
如果您的结果集是手动构造的,或者 NOT 返回为 IQueryable<>
或者不能自动链接,那么您将必须 Apply $expand
手动查询选项。
您可以这样做以仅允许扩展某些导航属性,下一个示例通过积极地将所有 History
记录加载到内存中来准备项目
Not recommended, especially if your navigation property may have many rows and the user will not be expanding very frequently, but it works:
[OData.EnableQuery]
public virtual MyStuff Get([FromODataUri] TKey key, ODataQueryOptions<MyStuff> queryOptions)
{
var item = dbContext.MyStuff.Include(X => x.History).Single(x => x.Id == 2);
return item;
}
这个例子仍然允许 EnableQueryAttribute
到 $expand
甚至 $sort
和 $filter
扩展中的记录,但是,因为整个可用数据已经加载到内存中,EnableQueryAttribute
无法加载其他端点。
in this last example, even though the
History
items were loaded into memory, the will only appear in the JSON response if the$expand=History
query option is provided by the caller.
还有很多其他场景,OP 没有提供他们的实现代码,所以这里全是推测。我特意 NOT 演示了如何手动 将 QueryOptions 应用于您的数据查询,您可以这样做,但在您掌握它之前,我鼓励您更接近于最小的实现,我们通过 OData 获得了很多 OOTB,通常足以应付。