LINQ to SQL - Борьба с запросом - PullRequest
       10

LINQ to SQL - Борьба с запросом

0 голосов
/ 03 августа 2009

У меня есть таблица с именами серверов и логинами. Мне нужно получить логины, которые являются общими для группы серверов.

Учитывая следующие данные:

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.

ДОПОЛНИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ:

С помощью Райана и некоторого поиска в Google различий в LINQ между VB и C # я получил следующее:

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 ]

2 голосов
/ 03 августа 2009

Вот что я придумал. Возможно, вы захотите проверить и выяснить, какой 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;
0 голосов
/ 03 августа 2009

Пока существует разумное практическое ограничение на количество передаваемых серверов, я бы выбрал что-то вроде этого:

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 сгенерирует что-то, что приведет к эффективному плану запроса. 1004 *

0 голосов
/ 03 августа 2009

Лично я считаю, что это хорошее место, чтобы НЕ использовать 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')").

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...