Linq 动态多条件group by
有个需求是要根据多个字段动态进行分组,具体效果如下
平常一般用的都是根据具体的字段的取进行分组的,百度一下发现已有解决方案。https://www.cnblogs.com/devindong/p/3615625.html
第一种是直接用动态拼接分组条件,缺点在于如果是多个分组条件的话,分组条件将变得非常难写,也很难写全
private static dynamic GroupBy(dynamic r) { int a = 1, b = 2; if (a < b) return new { id = r.id}; else if (a == b) return new { name=rd.name }; else return new { a = r.a }; }
还有一种是可以创建一个结构体来解决。需要注意的是,如果不用结构体而是选择class的话需要重写类的GetHashCode方法来重写类的相等判断方法。
该功能中构建的结构体为,根据相应的name group是为了拿key的时候取到对应的名称
public struct MassPatternDesignGroup { /// <summary> /// 波段Id /// </summary> public Guid? BandId { get; set; } /// <summary> /// 波段名称 /// </summary> public string BandName { get; set; } /// <summary> /// 设计师Id /// </summary> public Guid? DesignerId { get; set; } /// <summary> /// 设计师 /// </summary> public string DesignerName { get; set; } /// <summary> /// 品类Id /// </summary> public Guid? ProductCategoryId { get; set; } /// <summary> /// 品类名称 /// </summary> public string ProductCategoryName { get; set; } /// <summary> /// 主题Id /// </summary> public Guid? ThemePlanId { get; set; } /// <summary> /// 主题名称 /// </summary> public string ThemePlanName { get; set; } /// <summary> /// 系列Id /// </summary> public Guid? ProductSeriesId { get; set; } /// <summary> /// 系列名称 /// </summary> public string ProductSeriesName { get; set; } /// <summary> /// 廓形Id /// </summary> public Guid? SilhouetteId { get; set; } /// <summary> /// 廓形名称 /// </summary> public string SilhouetteName { get; set; } /// <summary> /// 款式来源Id /// </summary> public Guid? PatternPropertyId { get; set; } /// <summary> /// 款式来源名称 /// </summary> public string PatternPropertyName { get; set; } /// <summary> /// 销售渠道Id /// </summary> public Guid? SalesChannelsId { get; set; } /// <summary> /// 销售渠道名称 /// </summary> public string SalesChannelsName { get; set; } public string GetKey() { return $"{BandName} {DesignerName} {ProductCategoryName} {ThemePlanName} {ProductSeriesName} {SilhouetteName} {PatternPropertyName} {SalesChannelsName}"; } }
其中GetKey方法为获取分组条件。
group的model类为
public class MassPatternDesignGroupModel { /// <summary> /// 波段 /// </summary> public bool Band { get; set; } /// <summary> /// 设计师 /// </summary> public bool Designer { get; set; } /// <summary> /// 品类 /// </summary> public bool ProductCategory { get; set; } /// <summary> /// 主题 /// </summary> public bool ThemePlan { get; set; } /// <summary> /// 系列 /// </summary> public bool ProductSeries { get; set; } /// <summary> /// 廓形 /// </summary> public bool Silhouette { get; set; } /// <summary> /// 款式来源 /// </summary> public bool PatternProperty { get; set; } /// <summary> /// 销售渠道 /// </summary> public bool SalesChannels { get; set; } /// <summary> /// 品牌Id /// </summary> public Guid BrandId { get; set; } /// <summary> /// 年份 /// </summary> public int Year { get; set; } /// <summary> /// 季节Id /// </summary> public Guid SeasonId { get; set; } /// <summary> /// 机构Id /// </summary> public Guid OrganizationId { get; set; } public MassPatternDesignGroup GroupBy(dynamic r) { var g = new MassPatternDesignGroup(); if (Band) { g.BandId=r.BandId; g.BandName=r.BandName; } if (Designer) { g.DesignerId = r.DesignerId; g.DesignerName = r.DesignerName; } if (ProductCategory) { g.ProductCategoryId = r.ProductCategoryId; g.ProductCategoryName = r.ProductCategoryName; } if (ThemePlan) { g.ThemePlanId = r.ThemePlanId; g.ThemePlanName = r.ThemePlanName; } if (ProductSeries) { g.ProductSeriesId = r.ProductSeriesId; g.ProductSeriesName = r.ProductSeriesName; } if (Silhouette) { g.SilhouetteId = r.SilhouetteId; g.SilhouetteName = r.SilhouetteName; } if (PatternProperty) { g.PatternPropertyId = r.PatternPropertyId; g.PatternPropertyName = r.PatternPropertyName; } if (SalesChannels) { g.SalesChannelsId = r.SalesChannelsId; g.SalesChannelsName = r.SalesChannelsName; } return g; } }
其中的字段是前台传过来的分组项,分组时通过MassPatternDesignGroupModel调用GroupBy方法进行动态的多条件分组。
具体的调用如下
public ActionResult GetList(MassPatternDesignGroupModel model) { var result = new List<MassPatternDesignGroupQueryPanelDto>(); var massPatternDesignGroups = _designGroupQueryService.GetMassPatternDesignGroupQueryList(model.BrandId, model.Year, model.SeasonId, model.OrganizationId); var list= massPatternDesignGroups.GroupBy(a => model.GroupBy(a)).ToList();//动态分组 list.ForEach(a => { var dto=new MassPatternDesignGroupQueryPanelDto() { Title = a.Key.GetKey(), Items = a.OrderBy(b=>b.UUID).ToList() }; dto.TaskCount = dto.Items.Count(b => b.Type == MassPatternDesignGroupQueryType.任务); dto.DesignCount = dto.Items.Count(b => b.Type == MassPatternDesignGroupQueryType.设计); dto.ProofCount = dto.Items.Count(b => b.Type == MassPatternDesignGroupQueryType.打样); dto.MassCount = dto.Items.Count(b => b.Type == MassPatternDesignGroupQueryType.选款); result.Add(dto); }); return this.Direct(result); }
以上,就实现了Linq to Object多条件动态分组了。