Linq to sql LINQ到SQL-与查询抗争

Linq to sql LINQ到SQL-与查询抗争,linq-to-sql,set,Linq To Sql,Set,我有一个包含服务器名称和登录名的表。我需要检索一组服务器上常见的登录名 鉴于以下数据: ServerName Login ------------------------------- Server1 User1 Server2 User1 Server2 User2 我将传入Server1、Server2并只返回User1,因为User2与Server1没有关联 谁能告诉我如何在LINQtoSQL中实现这一点 我已经尝试了Contains,但它会返回

我有一个包含服务器名称和登录名的表。我需要检索一组服务器上常见的登录名

鉴于以下数据:

ServerName    Login
-------------------------------
Server1       User1
Server2       User1
Server2       User2
我将传入Server1、Server2并只返回User1,因为User2与Server1没有关联

谁能告诉我如何在LINQtoSQL中实现这一点

我已经尝试了Contains,但它会返回任何服务器上的所有用户,这和我所寻找的正好相反

编辑:我的一位同事成功地编写了我所追求的SQL版本

SELECT Login
  FROM ServerLogins
  WHERE ServerName IN ('Server1', 'Server2')
GROUP BY Login
HAVING count(Login) = 2
但我们都不知道如何将其转换为LINQ查询

附加编辑:

在Ryan的帮助下,通过谷歌搜索VB和C之间LINQ的差异,我完成了以下工作

Dim logins = From l In dc.ServerLogins _
             Where servers.Contains(l.ServerName) _
             Group l By l.Login Into Group _
             Where Group.Count() = servers.Count _
             Select Login
再次感谢大家的帮助


尼克

我个人认为这是一个不使用LINQtoSQL的好地方,而应该使用存储过程或标准SQL查询。我认为,即使您在Linq中提出了正确的查询,它也不会非常可读和/或高效

您所使用的SQL将如下所示:

SELECT Login
FROM ServerLogins
WHERE ServerName IN ('Server1', 'Server2')
GROUP BY Login
HAVING COUNT(*) = 2
public ICollection<Login> GetLoginsForServers(params string[] servers)
{
    if (servers == null || servers.Length == 0)
        return new List<Login>();

    var logins = db.Logins.Where(p => p.ServerName == servers[0]);
    for (int i=1; i<servers.Length; i++)
    {
        logins = logins.Intersect(db.Logins.Where(p => p.ServerName == servers[i]));
    }

    return logins.ToList();
}

请注意,最后一行中的2应该替换为上面“Server1”、“Server2”中列表中的服务器名称数。

以下是我的想法。如果您担心的话,您可能需要检查并找出它实际生成的SQL

List<string> servers = new List<string>{"Server1", "Server2"};

var logins = from l in context.ServerLogins
             where servers.Contains(l.ServerName)
             group l by l.Login into g
             where g.Count() == servers.Count
             select g.Key;

只要对传入的服务器数量有一个合理的实际限制,我就采用如下方式:

SELECT Login
FROM ServerLogins
WHERE ServerName IN ('Server1', 'Server2')
GROUP BY Login
HAVING COUNT(*) = 2
public ICollection<Login> GetLoginsForServers(params string[] servers)
{
    if (servers == null || servers.Length == 0)
        return new List<Login>();

    var logins = db.Logins.Where(p => p.ServerName == servers[0]);
    for (int i=1; i<servers.Length; i++)
    {
        logins = logins.Intersect(db.Logins.Where(p => p.ServerName == servers[i]));
    }

    return logins.ToList();
}

基本上,您从与第一个服务器关联的所有登录开始,然后通过与每个后续服务器关联的登录来限制它。由于查询在ToList之前不会执行,因此您仍然只需查询数据库一次,尽管查询本身肯定很难看,但希望LINQ2SQL提供程序生成一些能够产生高效查询计划的内容。

您能给我们提供您正在尝试的LINQ语句吗?您能给出一个代码示例吗?令人毛骨悚然,这正是我们刚刚提出的语句:这目前是在存储过程中完成的,但它使用一个连续数字表和一个临时表将以逗号分隔的服务器名称列表转换为一个临时表,运行in语句时将针对该临时表运行,我希望不必这样做,也不必在运行时将sql写入字符串接近这一点,但我得到了一个编译错误,方法g的定义在此上下文中是不可访问的。我不知道这是否是因为我在VB中工作。我认为这应该适用于C,但我对VB中的Linq不太熟悉。我正试着四处看看,也许我可以帮你把它修好。看起来你可能需要使用Group,而不仅仅是g。但是我真的不确定。。。我有一些网络问题,所以我无法访问许多合适的资源。使用此资源和您的指针,我已设法使其工作…请参阅更新后的工作代码。