我有一个包含服务器名称和登录名的表。我需要检索一组服务器中常见的登录信息。
鉴于以下数据:
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
再次感谢大家的帮助。
尼克
答案 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>