我正在使用延迟加载,并且担心性能。
假设我有一个对象A,其中包含对象B的列表。
我将使用延迟加载从数据库中检索对象A。这意味着如果我不访问它,将不会检索对象B的列表。
但是,如果我做这样的事情:
ObjectA.ObjectsB.Where(b => b.Id == 12);
它将查询所有对象B并对其进行过滤,还是仅查询表达式的结果?
答案 0 :(得分:1)
如果您使用的是SQL Server,则可以使用SQL Server Profiler查看SQL正在执行的查询类型。
我做了以下查询:
var context = new LabContextDb();
var user = context.Users.FirstOrDefault(x => x.Id == 1);
var roles = user.UserRoles.Where(x => x.UserId == 1).ToList();
我生成的SQL是:
SELECT TOP(1) [x].[Id] FROM [AbpUsers] AS [x] WHERE [x].[Id] = CAST(1 AS bigint)
exec sp_executesql N'SELECT [e].[Id], [e].[RoleId], [e].[UserId]
FROM [AbpUserRoles] AS [e]
WHERE [e].[UserId] = @__get_Item_0',N'@__get_Item_0 bigint',@__get_Item_0=1
但是,如果我做这样的事情:
var user = context.Users.FirstOrDefault(x => x.UserRoles.Any(y => y.Id == 1));
我的SQL将是这样的:
SELECT TOP(1) [x].[Id]
FROM [AbpUsers] AS [x]
WHERE EXISTS (SELECT 1
FROM [AbpUserRoles] AS [y]
WHERE ([y].[Id] = CAST(1 AS bigint)) AND ([x].[Id] = [y].[UserId]))
SQL Server Profiler是查看幕后情况的好方法。另一个提示是使用.ToList(),而不是如果您需要遍历大列表,那么自从您使用Where条件返回IQueryable(...)以来,每次循环都不会执行您的语句。
答案 1 :(得分:0)
好吧,在阅读了Flavio Francisco的答案之后,我用SQL事件探查器对自己进行了测试。
var objectA = (await _repo.Object.FindByCondition(obj => obj.Id == 3)).FirstOrDefault();
var objectB = objectA.ObjectsB.Where(obj => obj.Id == 1);
在事件探查器中,它首先进行调用以获取对象A,然后请求所有对象B。
因此,不幸的是,过滤器是在代码级别发生的。
答案 2 :(得分:0)
也许它将为您工作。
var objectB = (from objA in _repo.Object join objB in ObjectsB
on objA.Id equals objB.ObjectAId
where objA.Id == 3 && objB.Id == 1
select u).ToList();
为避免调用所有对象B。
答案 3 :(得分:0)