我有一组用户和访问。 (所以用户做访问)
访问具有用户导航属性。
我需要找到不会访问的用户。
我可以通过找到访问的用户,找到所有用户然后采取差异来做到这一点。
我试图找到一个更快的解决方案。
这就是我现在所拥有的:
var users = _db.Users.AsNoTracking().Include(c => c.City).Where(x => x.City.Id == city);
var groupedUsers = _db.Visits.AsNoTracking().Include(c => c.City).Include(a=>a.VisitedBy).Where(x => x.City.Id == city).GroupBy(x => x.VisitedBy).Select(group => new { VisitedBy = group.Key, Count = group.Count() });
var visitingUsers = groupedUsers.Select(user => user.VisitedBy);
var dif = users.Except(visitingUsers);
但是我在尝试GroupJoin如下:
var results = _db.Users.Include(c => c.City).Where(c => c.City.Id == city).
GroupJoin(_db.Visits.Include(c => c.City).Include(u => u.VisitedBy), u => u.Id, v => v.VisitedBy.Id, (u, v) => new { User = u , Visits = v })
.Select(o=>o.User);
但这给了我所有的用户,我希望用户不会在访问集中存在。
任何帮助?
答案 0 :(得分:3)
我不太确定城市过滤是否是您所追求的,但是以下应该达到您的目标:
var visitsToCity = _db.Visits.Where(v => v.City.Id == city);
var usersOfCity = _db.Users.Where(u => u.City.Id == city);
var nonVisitingUsers = usersOfCity.Where(u => !visitsToCity.Any(v => v.VisitedBy == u));
与Where
结合的最后一个Any
应该会产生如下SQL语句:
SELECT * FROM Users u WHERE u.CityId = @p0 AND
NOT EXISTS(SELECT 1 FROM Visits v WHERE v.CityId = @p0 AND
v.VisitedById = u.Id)
@p0
将提供city
的值。
答案 1 :(得分:3)
您可以通过使用null check实际执行左连接来避免其他答案中的相关子查询。这是一个简单的例子:
var A = new [] { new Foo { Bar = 1 }, new Foo { Bar = 2 }};
var B = new [] { new Foo { Bar = 2 }};
var C = from x in A
join y in B on x.Bar equals y.Bar into z
from y in z.DefaultIfEmpty()
where y == null
select x;
检查发出的SQL ...