如何为对标识符的每个部分获得区别

时间:2014-04-14 04:18:45

标签: c# linq entity-framework

我有一个表格,可以将卡车分配给用户,使用他们的身份将每个分配链接到各自的实体。只能选择卡车/用户的最后一次分配。我使用以下LINQ来获取我需要的值

var query = (from ta in TruckAllocations
         where ta.Truck.Name != null || !ta.Truck.Name.Contains(string.Empty)
         group ta by  ta.UserId into grp
         let MaxDate = grp.Max(g => g.CreatedOn)
         from g in grp
         where g.CreatedOn == MaxDate
         select new { Key = g.TruckAllocationId, Truck = g.TruckId, User = g.UserId, Date = g.CreatedOn });

我遇到的问题是分配给同一辆卡车的两个用户是查询结果,我只想要分配最后一个。结果示例

47      26  224 2014-03-28 10:47 AM
48      3   149 2014-03-31 10:25 AM
1048    2   575 2014-04-04 1:14 PM
1049    23  575 2014-04-09 9:15 AM
1050    56  322 2014-04-09 2:27 PM

如您所见,用户[2和23]被分配了相同的卡车[575]

我想要的结果是:

47      26  224 2014-03-28 10:47 AM
48      3   149 2014-03-31 10:25 AM
1049    23  575 2014-04-09 9:15 AM
1050    56  322 2014-04-09 2:27 PM

记录1048,因为他不是分配给卡车的最后一个用户而未显示。

有没有办法在对中获得区别,其中对中的每个值必须是唯一的

更新

我也试过

var query = (from ta in TruckAllocations
         where ta.Truck.Name != null || !ta.Truck.Name.Contains(string.Empty)
         group ta by  ta.TruckId into grp
         let MaxDate = grp.Max(g => g.CreatedOn)
         from g in grp
         where g.CreatedOn == MaxDate
         select new { Key = g.TruckAllocationId, Truck = g.TruckId, User = g.UserId, Date = g.CreatedOn });

结果是:

    6        54 3   2014-03-04 7:03 PM
    8        63 4   2014-03-13 12:36 PM
    10      626 4   2014-03-13 2:10 PM
    13       12 4   2014-03-20 4:18 PM
    21        8 3   2014-03-20 6:21 PM
    42       10 3   2014-03-21 1:09 PM
    43        3 26  2014-03-26 5:35 PM
    44       32 1   2014-03-27 8:53 AM
    47      224 26  2014-03-28 10:47 AM
    48      149 3   2014-03-31 10:25 AM
    1049    575 23  2014-04-09 9:15 AM
    1050    322 56  2014-04-09 2:27 PM

它确实只为卡车提供了一个卡车/用户,因为记录[1048]未被退回,但现在我已经使用4,3,26分配给多辆卡车,当他们只能分配一个

使用TruckId和UserId进行分组会将分配给两个用户的卡车添加到由TruckId分组的卡车中。

var query = (from ta in TruckAllocations
         where ta.Truck.Name != null || !ta.Truck.Name.Contains(string.Empty)
         group ta by  new {ta.TruckId, ta.UserId} into grp
         let MaxDate = grp.Max(g => g.CreatedOn)
         from g in grp
         where g.CreatedOn == MaxDate
         select new { Key = g.TruckAllocationId, Truck = g.TruckId, User = g.UserId, Date = g.CreatedOn });

** UPDATE2 **

得到我想要的解决方案是查询按UserId分组的表(有问题的第一个查询),然后查询由TruckId(有问题的第二个查询)分组的表。然后查询两个结果以获得卡车和用户的匹配,如下所示:

var assigned = (from t1 in query1
               from t2 in query2
               where t1.Truck == t2.Truck && t1.User == t2.User
               select new {t1.Key, t1.Truck, t1.User, t1.Date}).ToList();

想知道是否有更好的方法来做到这一点。

1 个答案:

答案 0 :(得分:2)

您可以执行类似的操作(组,按需要的元素降序排序)。

更习惯于流利的语法,所以......

var result = TruckAllocations
                .Where(ta => ta.Truck.Name != null && ta.Truck.Name != string.Empty)
                .GroupBy(ta => ta.UserId)
                //take the first element of each group, which will be the one with the max CreatedOn date
                .Select(g=> g.OrderByDescending(m => m.CreatedOn).First())
                .Select(m => new {
                   Key = m.TruckAllocationId, 
                   Truck = m.TruckId, 
                   User = m.UserId, 
                   Date = m.CreatedOn  
                });  

修改

您可以通过一步或两步完成此操作。

注意:如果给定用户使用的所有卡车后来被另一个用户使用=>此用户不会出现在列表中。

2步版

var lastDateByTruck = TruckAllocations
                    .Where(ta => ta.Truck.Name != null && ta.Truck.Name != string.Empty)
                    .GroupBy(m => m.TruckId)
                                   .Select(m => new
                                   {
                                       TruckId = m.Key,
                                       CreatedOn = m.Max(x => x.CreatedOn)
                                   });

var result = from allocation in TruckAllocations
                         join lastUsage in lastDateByTruck on new
                         {
                             allocation.TruckId,
                             allocation.CreatedOn
                         } equals new
                         {
                             lastUsage.TruckId,
                             lastUsage.CreatedOn
                         }
                         group allocation by allocation.UserId
                         into g
                         select new
                         {
                             UserId = g.Key,
                             TruckId = g.First().TruckId,
                             CreatedOn = g.First().CreatedOn

                         };

一体化语法流利:

var lastDateByTruck = TruckAllocations
                       .Where(ta => ta.Truck.Name != null && ta.Truck.Name != string.Empty)
                       .GroupBy(m => m.TruckId)
                       .Select(m => new
                       {
                           TruckId = m.Key,
                           CreatedOn = m.Max(x => x.CreatedOn)
                       })
                       .Join(TruckAllocations, x => new{x.TruckId, x.CreatedOn}, y => new{y.TruckId, y.CreatedOn}, (x, y) => y)
                       .GroupBy(m => m.UserId)
                       .Select(g => new
                       {
                           UserId = g.Key,
                           TruckId = g.First().TruckId,
                           CreatedOn = g.First().CreatedOn
                       });