Linq离开加入团体加入

时间:2015-02-19 19:48:33

标签: c# linq entity-framework

我有一组用户和访问。 (所以用户做访问)

访问具有用户导航属性。

我需要找到不会访问的用户。

我可以通过找到访问的用户,找到所有用户然后采取差异来做到这一点。

我试图找到一个更快的解决方案。

这就是我现在所拥有的:

  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);

但这给了我所有的用户,我希望用户不会在访问集中存在。

任何帮助?

2 个答案:

答案 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 ...