2011-02-10 75 views
1

我通过将数据源设置为通过执行LINQ查询获得的IQueryable对象来填充FormView。基本上它会返回在某个“班次”内持有某个“职位”的员工人数。帮助创建LINQ to SQL查询

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分组的各种方法,但看起来似乎无法解决这个问题。任何人都可以指引我走向正确的方向吗?

+1

如果你想** **所有的变化,你为什么检查'p.ShiftID'呢? –

+0

嗯,这对我来说很尴尬...... – Marcus

回答

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值获取值之前。

这可以通过引入你想要字典的位置标识数组并加入你的结果来解决。

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表等

+0

虽然我在解决问题之前解决了问题,但我一定可以在项目的另一部分使用它。谢谢。 – Marcus

0

我会建议看本集团通过实例here