EF Code首先是Eager loading和OrderBy问题

时间:2011-07-06 11:10:45

标签: linq entity-framework linq-to-entities ef-code-first eager-loading

我有两个实体,名为Category,Product with 1:n relation。

我希望得到一个类别,其中包含孩子们的孩子。

这是我的linq:

 _db.Categories.Where(c => c.CategoryID == catID)
    .Include(c => c.Products.OrderBy(p => p.ProductID))
    .SingleOrDefault();

由于orderby,此查询强制执行以下异常。

  

包含路径表达式必须引用   到定义的导航属性   类型。使用虚线路径   参考导航属性和   用于集合的Select运算符   导航属性。参数名称:   路径

2 个答案:

答案 0 :(得分:5)

无法订购或过滤预先加载的数据。这是linq-to-entities限制,如何在数据库中订购关系的唯一方法是使用projection:

var data =  _db.Polls
               .Where(c => c.CategoryID == pollID)
               .Select(c => new 
                   {
                       Pool = c,
                       Products = c.Products.OrderBy(p => p.ProductID)
                   })
               .SingelOrDefault();

您可以投影到匿名或自定义类型,但不能投影到映射类型(例如Poll)。

另一种方法是将其分为两个查询并使用显式加载:

var poll = _db.Polls.SingleOrDefault(c => c.CategoryID == pollID);
_db.Entry(poll).Collection(c => c.Products)
               .Query()
               .OrderBy(p =>.ProductID)
               .Load();

答案 1 :(得分:1)

Include必须引用导航属性,这意味着您不能包含OrderBy()。而不是:

_db.Categories
    .Where(c => c.CategoryID == catID)
    .Include(c => c.Products.OrderBy(p => p.ProductID))
    .SingleOrDefault();

......你必须使用它:

_db.Categories
    .Where(c => c.CategoryID == catID)
    .Include(c => c.Products)
    .SingleOrDefault();

...要为每个Products访问Category的有序列表,您可以将此属性添加到Category,如下所示:

class Category
{
    public IEnumerable<Product> OrderedProducts
    {
        get { return this.Products.OrderBy(p => p.ProductID); }
    }
}