我有以下查询:
model.Page = db.Pages
.Where(p => p.PageId == Id)
.Include(p => p.Series
.Select(c => c.Comics
.Select(col => col.Collection)))
.SingleOrDefault();
这很好用,虽然我现在需要通过名为'ReadingOrder'的属性来订购漫画。
我试过了:
model.Page = db.Pages
.Where(p => p.PageId == Id)
.Include(p => p.Series.Select(c => c.Comics.OrderBy(o => o.ReadingOrder)
.Select(col => col.Collection)))
.SingleOrDefault();
但是这会导致以下错误:
Include路径表达式必须引用导航属性 在类型上定义。使用虚线路径进行参考导航 属性和集合导航的Select运算符 属性。参数名称:路径
这个错误意味着什么?
提前致谢
修改
我的模特:
public class Page
{
public int PageId { get; set; }
public string Title { get; set; }
public ICollection<Series> Series { get; set; }
}
public class Series
{
public int SeriesId { get; set; }
public int PageId { get; set; }
public string Title { get; set; }
public Page Page { get; set; }
public ICollection<Comic> Comics { get; set; }
}
public class Comic
{
public int ComicId { get; set; }
public string Title { get; set; }
public int ReadingOrder { get; set; }
public string Subtitle { get; set; }
public int CollectionId { get; set; }
public Collection Collection { get; set; }
}
public class Collection
{
public int CollectionId { get; set; }
public string Title { get; set; }
public ICollection<Comic> Comics { get; set; }
}
答案 0 :(得分:10)
异常“ ...包含路径表达式必须引用导航属性... ”基本上抱怨c.Comics.OrderBy
不是导航属性。 (我认为这是合理的投诉。)
实际上,EF不支持在急切加载语句(Include
)中应用排序(以及过滤)。
那么,你能做什么?
选项1:
加载实体后在内存中排序:
model.Page = db.Pages
.Where(p => p.PageId == Id)
.Include(p => p.Series.Select(c => c.Comics
.Select(col => col.Collection)))
.SingleOrDefault();
if (model.Page != null)
{
foreach (var series in model.Page.Series)
series.Comics = series.Comics.OrderBy(c => c.ReadingOrder).ToList();
}
很丑,但是因为你显然只是通过id加载一个Page
对象,它可能比以下选项更快(LINQ to Objects in memory)(如果Series
和Comics
集合不是特别长。)
选项2:
将查询分解为混合了eager和explicite loading的部分:
model.Page = db.Pages
.Where(p => p.PageId == Id)
.Include(p => p.Series) // only Series collection is included
.SingleOrDefault();
if (model.Page != null)
{
foreach (var series in model.Page.Series)
db.Entry(series).Collection(s => s.Comics).Query()
.Include(c => c.Collection)
.OrderBy(c => c.ReadingOrder)
.Load(); // one new DB query for each series in loop
}
选项3:
投影?
Here和here就像多个导航属性的复杂Include
链的危险性一样。它可以加载大量的重复数据。 Include
确保您只有一次数据包往返,但可能会以更多传输数据为代价。 Explicite加载有多个往返,但总共可能有更少的数据。
(我知道,我给了你这个包括......选择......选择......选择......链,但我怎么知道你会认真对待我:)。那么,根据嵌套集合的大小,它仍然是最佳选择。)
答案 1 :(得分:0)
脱离我的头顶,未经测试:
model.Page = db.Pages
.Where(p => p.PageId == Id)
.Include(p => p.Series
.Select(c => c.Comics
.Select(col => col.Collection)
.OrderBy(o => o.ReadingOrder)))
.SingleOrDefault();