如果我在Web项目中使用我的实体模型,我可以很好地导航到1- * 1-0.1导航属性...但是当我在我的oData服务中通过LinqPad加载完全相同的对象时,nav属性始终为null
......我做错了什么?......应该以某种方式启用吗?
如果我加载fiddler并运行查询http://odata.site.com/Service1.svc/usda_FOOD_DES(1001)/usda_ABBREV
...它返回正确的结果
谢谢, 史蒂夫
答案 0 :(得分:4)
Customers.Where(c => c.ID == 1).Single().Orders
原因是与Entity Framework的导航属性不同,当您访问OData实体的属性时,它不会自动返回到数据源并检索任何尚未存在的数据。因此,当您从OData Feed中检索实体时,默认情况下它不包含链接的实体,因此您可以获得一对多或多对多导航属性的空IEnumerable<T>
或单实体导航属性为null。 / p>
您希望上述查询转换为:
的http; // odata.sample.com/MyODataFeed.svc/Customers(1)/订单
哪个会返回所有订单,而是转换为此(要在LINQPad中查看查询,请单击结果窗格上方的SQL按钮):
的http; // odata.sample.com/MyODataFeed.svc/Customers(1)
这是因为最后的.Orders
不在任何扩展方法中,因此不参与IQueryable的构造。因此,它不会反映在从查询构造的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)$扩大=订单&安培; $选择=订单
我不明白为什么这根本就没有翻译成/ Customers(1)/ Orders。在任何情况下,它都将订单列表放在一个不需要的包装器类中,这可能非常烦人,但它确实有效,而且它是我能够检索到导航属性内容的最接近的。
我更喜欢的方法是包括每个客户的所有订单,如下所示:
Customers.Expand("Orders").Where(c => c.ID == 1).Single().Orders
这会产生以下查询:
的http; // odata.sample.com/MyODataFeed.svc/Customers(1)$扩大=订单
这样可行,但缺点是包含我们可能不需要的所有客户详细信息。此外,.Expand(...)
的字符串是有问题的 - 它的类型很弱,所以它不会被编译器验证(提防拼写错误),并非所有重构工具都会重构它,找到所有用法该属性不会在搜索结果中包含该字符串等。
答案 1 :(得分:0)
来自http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/working-with-entity-relations的最新v4 Asp.Net oData支持 使用导航属性有一个更简洁的解决方案。
支持网址:
GET /Products(1)/Supplier
引用: 这里“供应商”是产品类型的导航属性。在这种情况下,供应商引用单个项目,但导航属性也可以返回集合(一对多或多对多关系)。
要支持此请求,请将以下方法添加到ProductsController
类:
// GET /Products(1)/Supplier
public Supplier GetSupplier([FromODataUri] int key)
{
Product product = _context.Products.FirstOrDefault(p => p.ID == key);
if (product == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return product.Supplier;
}
关键参数是产品的关键。该方法返回相关实体 - 在本例中为Supplier实例。方法名称和参数名称都很重要。通常,如果导航属性名为“X”,则需要添加名为“GetX”的方法。该方法必须采用名为“key”的参数,该参数与父键的数据类型匹配。
在key参数中包含[FromOdataUri]
属性也很重要。此属性告诉Web API在从请求URI解析密钥时使用OData语法规则。