这是THIS的后续问题。
我遇到了同样的问题,但解决方案对我来说不起作用 我有如下查询:
item = db.Categories
.Include(i => i.AccessRight.Roles).Include(i => i.AccessRight.Permissions)
.Select(i => new ContentItemWithRevision<Category, ContentRevision>()
{
Item = i,
AccessRight = i.AccessRight,
Roles = i.AccessRight.Roles,
Permissions = i.AccessRight.Permissions,
Revision = i.Revisions.OrderByDescending(r => r.DateCreated).FirstOrDefault()
})
.FirstOrDefault(c => c.Item.Id == id);
选择中的AccessRight
,Roles
和Permissions
添加到&#34;技巧&#34;由于我不查询Include
,因此忽略了查询中entity type
的急切加载。
但这不起作用,因为我悄悄话。 item.Item.AccessRight
AccessRight = i.AccessRight
加载了Select
,我可以在我只能传递item.Item
但item.Item.AccessRight.Roles
和item.Item.AccessRight.Permissions
的视图中使用item.Roles
不是(但item.Permission
和Include
已正确加载。)
所以这似乎是&#34;技巧&#34;只适用于&#34;一个级别&#34;。
有没有办法解决这个问题?
现在是否有办法使用新版本的EF来使item.Item
正常工作,因为这将是IMO的最佳解决方案?
或者我可以至少使用&#34;多个级别&#34;?
我目前唯一可以解决的解决方案是不通过item
,而是通过item.Roles
并使用item.Item.AccessRight.Roles
代替item.Item.AccessRight.Roles
,但这不是很直观(当一些人使用Include
因为他不知道问题时崩溃)并且在我的应用程序中需要进行一些更改。
我也尝试在Select
之后使用Select
,但是在我entity type
Category
之后我再次使用了Revision
。
也许我的基本问题也有完全不同的解决方案:
我只想选择我的1:n
及其最新Category:Revisions
而不是所有修订(因为这些可能很多)。如果有一个解决方案没有我的自定义类型,我也可以使用该解决方案。
更新:
这是我的DB的简化模型:
因此1:1
为Category:AccessRight
,n:m
为AccessRights:Roles
,AccessRights:Permissions
和var category = db.Categories
.Include(i => i.AccessRight.Roles)
.Include(i => i.AccessRight.Permissions)
.Include(i => i.Revisions)
.FirstOrDefault(i => i.Id == id);
为{{1}}。
以下查询也可以,但获得所有修订,而不仅仅是最新版本:
{{1}}
答案 0 :(得分:1)
现在你已经更新了你的问题,我可以解释你能做什么和不该做什么,以及为什么。
在您的工作查询中,您从数据库中获取整个实体(Category
),其中包含所有相关的导航属性(AccesRight.Roles
,AccesRight.Permissions
和Revisions
急切地装着。到目前为止一切顺利:
var category = db.Categories
.Include(i => i.AccessRight.Roles)
.Include(i => i.AccessRight.Permissions)
.Include(i => i.Revisions)
.FirstOrDefault(i => i.Id == id);
但现在您的要求是仅加载Revisions
集合中的最后一个修订版。如果你这样做,你会作弊:语义category.Revisions
是&#34;此类别的所有修订&#34;。如果您使用该属性仅加载最后一个修订版,那么您将破坏该语义。即便如此,这是可能的,但不可取。但是,使用单个查询无法完成:必须完成加载所有相关实体,但Revisions
,然后显式加载修订,但过滤它们,如下所示:
ctx.Configuration.LazyLoadingEnabled = false;
var catWithRev = ctx.Categories
.Include(c => c.AccessRight.Roles)
.Include(c => c.AccessRight.Permissions)
//.Include(c => c.Revisions) -- not eagerly loaded
.FirstOrDefault(i => i.Id == id);
// Explicitly load the filtered revisions
ctx.Entry(catWithRev).Collection(cwr => cwr.Revisions).Query()
.OrderByDescending(r => r.DateCreated).Take(1)
.Load();
现在,你有自己想要的东西,但要考虑这些因素:
因此,创建一个包含所有相关导航属性的对象,但修订版和最后一个修订版,如下所示会更好:
var catWithRev = ctx.Categories
.Include(c => c.AccessRight.Roles)
.Include(c => c.AccessRight.Permissions)
//.Include(c => c.Revisions)
.Select(c => new
{
Category = c,
LastRevision = c.Revisions
.OrderByDescending(r => r.DateCreated)
.FirstOrDefault()
})
.FirstOrDefault(i => i.Id == id);
通过这种方式,所有数据都加载到一个查询中,并且语义正确。您可以使用匿名类型,例如示例代码,或者专门为此创建一个类。
(注意:此代码经过测试并正常运行)