我的数据库结构是这样的:OptiUser
通过UserGroup
表属于多个IdentityMap
,这是一个匹配表(多对多),附加了一些附加属性。每个UserGroup
都有多个OptiDashboard
s。
我有一个GUID字符串,用于标识特定用户(此代码中为wlid
)。我希望得到IEnumerable
标识的用户OptiDashboards
的所有wlid
。
这两个Linq-to-Entities查询中哪一个最有效?它们是否在后端运行相同的方式?
另外,我可以将选项2的Include
语句缩短为.Include("IdentityMaps.UserGroup.OptiDashboards")
吗?
using (OptiEntities db = new OptiEntities())
{
// option 1
IEnumerable<OptiDashboard> dashboards = db.OptiDashboards
.Where(d => d.UserGroups
.Any(u => u.IdentityMaps
.Any(i => i.OptiUser.WinLiveIDToken == wlid)));
// option 2
OptiUser user = db.OptiUsers
.Include("IdentityMaps")
.Include("IdentityMaps.UserGroup")
.Include("IdentityMaps.UserGroup.OptiDashboards")
.Where(r => r.WinLiveIDToken == wlid).FirstOrDefault();
// then I would get the dashboards through user.IdentityMaps.UserGroup.OptiDashboards
// (through foreach loops...)
}
答案 0 :(得分:4)
您可能误解了Include
函数实际执行的操作。选项1纯粹是一种查询语法,它对实体框架返回的内容没有影响。使用Include
函数的选项2在返回查询结果时指示实体框架 Eagerly Fetch 来自数据库的相关行。
因此选项1将导致一些连接,但查询的“选择”部分将仅限于OptiDashboards
表。
选项2也会导致连接,但在这种情况下,它将返回所有所包含的表的结果,这显然会带来更多的性能损失。但与此同时,结果将包括您需要的所有相关实体,避免[可能]需要更多往返数据库。
答案 1 :(得分:0)
我认为Include
将呈现为joins
,您将能够从您的用户对象中的那些表中访问数据(Eager Loading the properties)。
Any
查询将呈现为exists
,而不会使用其他表格中的信息加载用户对象。
为了获得最佳性能,如果您不需要其他信息,请使用Any
查询
答案 2 :(得分:0)
正如已经指出的那样,第一种选择几乎肯定会表现得更好,仅仅因为它会检索更少的信息。除此之外,我想指出你也可以用这种方式编写查询:
var dashboards =
from u in db.OptiUsers where u.WinLiveIDToken == wlid
from im in u.IdentityMaps
from d in im.UserGroup.OptiDashboards
select d;
我希望上述内容的表现与第一个选项类似,但您可能(或可能不)更喜欢上述表格。