如果我在 Web 项目中使用我的实体模型,我可以很好地导航到 1-* 1-0.1 导航属性...但是当我通过 LinqPad 在我的 oData 服务中加载完全相同的对象时,导航属性始终为 null
...我做错了什么吗?...应该以某种方式启用它吗?
如果我加载 fiddler 并运行查询 http://odata.site.com/Service1.svc/usda_FOOD_DES(1001)/usda_ABBREV
...它返回正确的结果
谢谢, 史蒂夫
最佳答案
我问过自己同样的问题。我想知道为什么以下返回一个空集合:
Customers.Where(c => c.ID == 1).Single().Orders
原因是,与 Entity Framework 的导航属性不同,当您访问 OData 实体的属性时,它不会自动返回到数据源并检索任何不存在的数据。因此,当您从 OData 源中检索实体时,默认情况下它不包含链接的实体,因此您会得到一个空的 IEnumerable<T>
。对于一对多或多对多导航属性,或者对于单个实体导航属性为 null。
您希望上述查询转换为:
http;//odata.sample.com/MyODataFeed.svc/Customers(1)/Orders
它会返回所有订单,但它会转换成这样(要在 LINQPad 中查看查询,请单击结果 Pane 上方的 SQL 按钮):
http;//odata.sample.com/MyODataFeed.svc/Customers(1)
这是因为 .Orders
最后不在任何扩展方法中,因此不参与 IQueryable 的构造。因此它不会反射(reflect)在从查询构造的 URL 中,也不包含在结果集中。
那么您如何才能只获得客户 1 的订单呢?您可以尝试使用以下查询解决此问题:
Customers.Where(c => c.ID == 1).Select(a => c.Orders)
这应该会导致 .Orders
要包含在查询中的属性。不幸的是,.Select(...)
不将结果投影到匿名方法(即 new { ... }
)是不允许的,并抛出 NotSupportedException: The method 'Select' is not supported.
多可惜。那么:
Customers.Where(c => c.ID == 1).Select(a => new { c.Orders })
这不会产生预期的结果,而是执行以下查询:
http;//odata.sample.com/MyODataFeed.svc/Customers(1)?$expand=Orders&$select=Orders
我不明白为什么不将其翻译成/Customers(1)/Orders。在任何情况下,它都会将订单列表放在一个不需要的包装类中,这可能会很烦人,但它确实有效,而且它是我最接近仅检索导航属性内容的方法。
我更喜欢的方法是包括每个客户的所有订单,如下所示:
Customers.Expand("Orders").Where(c => c.ID == 1).Single().Orders
这会产生以下查询:
http;//odata.sample.com/MyODataFeed.svc/Customers(1)?$expand=Orders
这可行,但缺点是包含了我们可能不需要的所有客户详细信息。此外,.Expand(...)
的字符串性有问题——它的类型很弱,所以它不会被编译器验证(注意拼写错误),并不是所有的重构工具都会重构它,找到那个属性的所有用法不会在搜索结果中包含那个字符串,等
关于wcf - 为什么我的 oData 服务( Entity Framework )不允许导航属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7642489/