LINQ GroupBy,同时保留所有对象字段

时间:2012-11-15 15:15:51

标签: c# .net linq lambda

我目前有这个样本数据表:

ID  | Policy ID     |   History ID  | Policy name
1   |   1           |    0          | Test
2   |   1           |    1          | Test
3   |   2           |    0          | Test1
4   |   2           |    1          | Test1

除此之外,我想按照策略ID和历史ID(MAX)进行分组,因此我想保留的记录是ID 2和4:

   ID   | Policy ID     |   History ID  | Policy name
    2   |   1           |    1          | Test
    4   |   2           |    1          | Test1

我曾尝试在LINQ中执行此操作,并且每次都遇到同样的问题。我可以对我的实体进行分组,但总是进入一个我必须重新定义属性的组,而不是将它们与我的Policy对象保持一致。如:

var policies = _context.Policies.GroupBy(a => a.intPolicyId)
                                            .Select(group => new {
                                                PolicyID = group.Key,
                                                HistoryID = group.Max(a => a.intHistoryID)
                                            });

这只是简单地列出了包含“策略ID”和“历史ID”的对象列表。我想要从Policies对象返回的所有属性,而不必全部重新定义它们,因为此对象中有大约50个属性。

我试过了:

        var policies = _context.Policies.GroupBy(a => a.intPolicyId)
                                                    .Select(group => new {
                                                        PolicyID = group.Key,
                                                        HistoryID = group.Max(a => a.intHistoryID)
                                                        PolicyObject = group;
                                                    });

但这出错了。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

按组合键分组

_context.Policies.GroupBy(a => new {a.intPolicyId, *other fields*}).Select(
    group=> new {
        PolicyId = group.Key.intPolicyId,
        HistoryId = group.Max(intHistoryId),
        *other fields*
    }
);

另一种方式 - 抓住历史记录,而不是加入其他数据,这样的事情(不会开箱即用,需要一些改进)

var historyIDs = _context.Policies.GroupBy(a=>a.intPolicyId).Select(group => new {
                                            PolicyID = group.Key,
                                            HistoryID = group.Max(a => a.intHistoryID)
                                        });

var finalData = from h in historyIDs
                join p in _context.Policies on h.intPolicyId equals p.intPolicyId
                select new {h.HistoryId, *all other policy fields*}

另一种方式,即使更简单,也不需要大量输入:):

var historyIDs = _context.Policies.GroupBy(a=>a.intPolicyId).Select(group => new {
                                            PolicyID = group.Key,
                                            HistoryID = group.Max(a => a.intHistoryID)
                                        });

var finalData = from h in historyIDs
                join p in _context.Policies on h.PolicyId equals p.intPolicyId && h.HistoryId equals p.HistoryId
                select p

基本上它与以下SQL查询有些相同:

select p.*
from Policy p
inner join (
    select pi.policyId, max(pi.historyId)
    from Policy pi
    group by pi.policyId
) pp on pp.policyId = p.policyId and pp.historyId = p.historyId

答案 1 :(得分:0)

在LINQ to Objects中,我将其作为

执行此操作
var policies = _context.Policies
    .GroupBy(a => a.intPolicyId)
    .Select(g => g.OrderByDescending(p => p.intHistoryID).First());

但是您的_context实施可能涉及数据库,我并不是百分之百确定这会转化。

基本上它按照您的预期按策略ID进行分组,然后在每个组中按历史记录ID排序,并从每个组中选择具有最高历史ID的行。它返回与Policies中的类型完全相同的类型。