LINQ to SQL - 在查询中苦苦挣扎

时间:2009-08-03 13:33:19

标签: linq-to-sql set

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

鉴于以下数据:

ServerName    Login
-------------------------------
Server1       User1
Server2       User1
Server2       User2

我会传入Server1,Server2并仅返回User1,因为User2与Server1没有关联。

有谁能告诉我如何在LINQ to SQL中实现这一目标?

我尝试过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

再次感谢大家的帮助。

尼克

3 个答案:

答案 0 :(得分:2)

这是我想出的。如果你担心它,你可能想检查并找出它实际产生的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;

答案 1 :(得分:0)

我个人认为这是一个不使用Linq to SQL而是使用sproc或标准SQL查询的好地方。我认为,即使你在Linq中提出正确的查询,它也不会非常易读和/或效率高。

您将拥有的SQL看起来像这样:

SELECT Login
FROM ServerLogins
WHERE ServerName IN ('Server1', 'Server2')
GROUP BY Login
HAVING COUNT(*) = 2

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

答案 2 :(得分:0)

只要对传入的服务器数量有合理的实际限制,我会选择以下内容:

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提供程序能够生成一些能够产生高效查询计划的东西。 / p>

相关问题