我有一个类型为Complex的实体对象。
复合体与论坛的比例为1:1,论坛中有很多主题,每个主题都有很多帖子。我正在尝试对帖子进行分页,但收到我不理解的错误。
Message = ThenInclude属性lambda表达式'p => {p.Posts => Skip((__ pageIndex_0-1))=> Take(__ pageSize_1)}'无效。该表达式应表示属性访问:“ t => t.MyProperty”。要定位在派生类型上声明的导航,请指定目标类型的显式键入的lambda参数,例如'((衍生d)=> d.MyProperty'。
这有效..
public Complex GetComplexWithForumAndPosts(Guid Id, int pageIndex, int pageSize = 10)
{
var complex = CoDBContext.Complexes
.Include(x => x.Forum)
.ThenInclude(x => x.Topics)
.ThenInclude(p => p.Posts)
.Single(x => x.Id == Id);
return complex;
}
但这不是
public Complex GetComplexWithForumAndPosts(Guid Id, int pageIndex, int pageSize = 10)
{
var complex = CoDBContext.Complexes
.Include(x => x.Forum)
.ThenInclude(x => x.Topics)
.ThenInclude(p => p.Posts.Skip((pageIndex-1)*pageSize).Take(pageSize))
.Single(x => x.Id == Id);
return complex;
}
答案 0 :(得分:2)
Include
不包含的内容 Include
方法是个bit子。接受表达式参数的最常用重载(如果存在内存,则自Entity Framework 4.1起就存在)看起来令人怀疑,就像那些通用的LINQ方法用我们提供的最疯狂的表达式来处理各种奇妙的事情一样。
实际上,它和ThenInclude
-都是不是 LINQ方法。 (Then)Include
只是一种坚固的旧方法,拒绝执行其单一任务之外的任何操作:将导航属性名称传递给EF查询引擎,指示其急于加载具有根实体的集合或引用。可以将其视为Include("PropertyName")
的强类型版本。它的 only 目的是启用编译类型类型检查。
这意味着:您只能使用表示导航属性名称的表达式:.ThenInclude(p => p.Posts)
是可以的。没有添加任何东西。
expression参数使人们期望它做得更多。那么为何不?代码可以编译,为什么不运行?但不是。常见的失望之处是Include
无法被过滤或排序。结合Include
和Skip/Take
的工作虽然不常见,但同样可以理解。
对于我来说,EF团队不妨考虑完全放弃这种(Then)Include
的重载,现在我们有了nameof
关键字,它可以做类似的事情并且可以同样地使用。这将消除所有混乱,无休止地涌入Stack Overflow问题,以及迄今为止从未被映射的永无止境的变更请求。 [也可以理解,但这超出了此问题的范围]。
与此同时,您仍然遇到问题。 Skip/Take
经常不与Include
结合使用的原因是很难想象它应该做什么。只是假设您在其中嵌套了两个Includes
或ThenInclude(x => x.Topics.Skip().Take().ThenInclude(p => p.Posts))
(如果有支持,则应该都是同等合法的){em>两个。实际上,只有在查询的根实体上进行分页才是明确定义的。
因此,您只能通过查询帖子来获取分页的帖子。例如这样的
CoDBContext.Posts
.Where(p => p.Topic.Forum.ComlexId = Id)
.Skip((pageIndex-1)*pageSize).Take(pageSize))
这也是比带有Includes
的查询更精简的查询。
如果您需要更多上下文信息,例如在Complex
上,可以考虑在一次呼叫中查询Complex
,将其保留在页面上(如果这是SPA)并查询帖子在随后的ajax调用中。