Помогите создать запрос LINQ to SQL - PullRequest
1 голос
/ 11 февраля 2011

Я заполняю FormView, устанавливая источник данных для объекта IQueryable, который я получаю, выполняя запрос LINQ. По сути, он возвращает количество сотрудников, которые занимают определенную «должность» в рамках определенной «смены».

int shiftID = 1;
var shiftCount = from x in context.Employees.Take(1)
                 select new
                 {
                 ManagerCount = ((from p in context.Persons
                              where p.PositionID == 1 && p.ShiftID == shiftID && p.IsEmployee == true
                              select p.PersonId).Count(),
                PartTimeCount = ((from p in context.Persons
                              where (p.PositionID == 2 || p.PositionID == 3) && p.ShiftID == shiftID && p.IsEmployee == true
                              select p.PersonId).Count(),
                 etc, etc...
                 };

Эта часть отлично работает. Однако, когда я хочу получить число сотрудников за все смены, я не могу понять, как это сделать:

//Get all shifts 1, 2, and 3
var shiftCount = from x in context.Employees.Take(1)
                 select new
                 {
                 ManagerCount = ((from p in context.Persons
                              where p.PositionID == 1 && (p.ShiftID == 1 || p.ShiftID == 2 || p.ShiftID == 3) && p.IsEmployee == true
                              select p.PersonId).Count()
                 };

Это не работает, потому что, конечно, возвращает 3 значения и выдает ошибку Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression..
Поэтому мне нужно получить сумму возвращенных трех значений (хотя это не всегда три, это зависит от позиции).
Я смотрел на различные способы использования Sum и LINQ группировки, но, похоже, не могу решить это. Кто-нибудь может указать мне правильное направление?

Ответы [ 2 ]

0 голосов
/ 11 февраля 2011

У меня есть несколько ответов для вас, но сначала кажется, что у вас что-то не так с вашей первой частью вашего запроса.Вы делаете .Take(1) на Employees, что даст вам только одно значение x.Поскольку вы не используете x в оставшейся части запроса, тогда использование Employees является излишним.

Теперь, поскольку все ваши запросы очень похожи, я попытался удалить повторение.Первое, что нужно сделать, это получить общий фильтр для смен, по которым вы фильтруете.

Если у вас есть одна смена, используйте это:

int shiftID = 1;
var shifts = new [] { shiftID, };

Если у вас несколько смен,используйте это:

var shifts = new [] { 1, 2, 3, };

В любом случае вы получите массив целых чисел, представляющих сдвиги, по которым вы хотите фильтровать.Для всех приведенных ниже ответов требуется этот массив shifts.

Затем определите запрос для сотрудников в эту смену, независимо от должности на данный момент.

var employeesInShifts =
    from p in context.Persons
    where p.IsEmployee
    where shifts.Contains(p.ShiftID)
    select p;

Таким образом, вы можете получитьсчетчик сдвигов выглядит следующим образом:

var shiftCount =
    new
    {
        ManagerCount = employeesInShifts
            .Where(p => p.PositionID == 1)
            .Count(),
        PartTimeCount = employeesInShifts
            .Where(p => p.PositionID == 2 || p.PositionID == 3)
            .Count(),
        // etc
    };

Возможно, лучшая альтернатива для вас - преобразовать запрос employeesInShifts в словарь, а затем просто извлечь значения из словаря.

var employeesInShifts =
    (from p in context.Persons
     where p.IsEmployee
     where shifts.Contains(p.ShiftID)
     group p by p.PositionID into gps
     select new
     {
        PositionID = gps.Key,
        Count = gps.Count(),
     })
    .ToDictionary(pc => pc.PositionID, pc.Count);

var shiftCount =
    new
    {
        ManagerCount = employeesInShifts[1],
        PartTimeCount = employeesInShifts[2] + employeesInShifts[3],
        // etc
    };

Недостатком этого подхода является то, что вы действительно должны проверить, что в словаре есть значения для каждого PositionID, прежде чем получать значения.

Это можно исправить, введя массив идентификаторов позиций, который вы хотитесловарь, чтобы иметь и объединить ваши результаты по этому.

var positionIDs = new [] { 1, 2, 3, };

var employeesInShifts =
    (from p in context.Persons
     where p.IsEmployee
     where shifts.Contains(p.ShiftID)
     where positionIDs.Contains(p.PositionID)
     select p).ToArray();

var allPositionEmployeesInShifts =
    from pid in positionIDs
    join p in employeesInShifts on pid equals p.PersonId into gps
    select new
    {
        PositionID = pid,
        Count = gps.Count(),
    };

var countOfPositionID =
    allPositionEmployeesInShifts
        .ToDictionary(x => x.PositionID, x => x.Count);

var shiftCount =
    new
    {
        ManagerCount = countOfPositionID[1],
        PartTimeCount = countOfPositionID[2] + countOfPositionID[3],
        // etc
    };

Теперь это гарантирует, что ваш окончательный словарь будет содержать количество всех идентификаторов позиций, которые вы хотите запросить.

ПустьЯ знаю, работает ли это или вам действительно нужно присоединиться к столу Employees и т. д.

0 голосов
/ 11 февраля 2011

Я бы порекомендовал посмотреть на Группу. Примеры здесь :

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