帮助创建LINQ to SQL查询

时间:2011-02-10 23:38:59

标签: c# linq linq-to-sql

我通过将数据源设置为通过执行LINQ查询获得的IQueryable对象来填充FormView。基本上,它返回在某个“Shift”内持有某个“位置”的员工数量。

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 :(得分:0)

我建议查看分组示例here

答案 1 :(得分:0)

我已经为您找到了一些答案,但首先您的查询的第一部分似乎有问题。您在.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的值。

可以通过引入您希望字典具有的位置ID数组并在其上加入结果来解决这个问题。

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
    };

现在可以保证您的最终字典将包含您想要查询的所有位置ID的计数。

请告诉我这是否有效,或者您是否真的需要加入Employees表等。