
语言集成查询:Language Integrated Query是微软一项很好的技术和工具,可以方便程序员对数据集进行操作。
Linq有两种使用方式,一种是linq子句,一种是拓展方法,二者是一样的,但拓展方法更整洁好用。
扩展方法:使你能够向现有类型“添加”方法(包括你自定义的类型和对象噢),而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但是可以像扩展类型上的实例方法一样进行调用。
System.Linq说明文档
本文主要记录了Linq拓展方法Join和GroupJoin的使用。
三个类表关系如下
【菜单】包含多个【子模块】,【子模块】可以属于多个【菜单】。多对多关系通过【包含】联系关联。【子模块】是一棵树,自身通过属性“父节点”实现自身嵌套。
实现代码如下:
////// 菜单 /// public class Menu1 { public int ID { get; set; } public string Name { get; set; } ////// 菜单包含模块 /// [SqlSugar.SugarColumn(IsIgnore = true)] public ListModels { get; set; } } /// /// 模块 /// public class Model { public int ID { get; set; } public string Name { get; set; } public int ParentID { get; set; } ////// 子模块 /// [SqlSugar.SugarColumn(IsIgnore = true)] public ListChildren { get; set; } } /// /// 菜单模块关系 /// public class Relation { public int MenuID { get; set; } public int ModelID { get; set; } ////// 模块ID对应模块内容 /// [SqlSugar.SugarColumn(IsIgnore =true)] public Model Model { get; set; } } public static class Main { public static void Test() { //SqlSugar仓储模式查询数据 //菜单 var menuDal = new BaseServices(); List menus = menuDal.Query().Result; //菜单-模块关系 var menuModelDal = new BaseServices (); List menuModels = menuModelDal.Query().Result; //模块 var modellDal = new BaseServices (); //Result是异步方法,ToTree是SqlSugar将结果转化为tree List models = modellDal.Queryable().Result.ToTree(it => it.Children, it => it.ParentID, 0); //1、将模块与menumodel关联在一起 var newMenuModels = menuModels.Join (models, p => p.ModelID, q => q.ID, (p, q) => new Relation() { MenuID = p.MenuID, ModelID = p.ModelID, Model = q }); //2、将菜单和菜单-模块关联在一起 var newMenu = menus.GroupJoin (newMenuModels, p => p.ID, q => q.MenuID, (p, q) => new Menu1() { ID = p.ID, Name = p.Name, Models = q.Where(r => r.MenuID == p.ID) .Select(s => s.Model).ToList(), } ).ToList(); } }
方法详细分析如下:
Join:基于匹配键对两个序列的元素进行关联。
Join
(IEnumerable , IEnumerable , Func , Func , Func )
类型参数
TOuter:第一个序列中的元素的类型。
TInner:第二个序列中的元素的类型。
TKey:键选择器函数返回的键的类型。
TResult:结果元素的类型。
参数
outer:IEnumerable
inner:IEnumerable
outerKeySelector:Func
innerKeySelector:Func
resultSelector:Func
返回
IEnumerable
使用分析:Join是左连接,函数参数中前四个都好理解,分别是左数据源、右数据源,左数据源的主键和右关联件的外键(第一项this不是参数,是指调用方法的实例对象)。第五项为结果处理,即如何返回指定类型的结果。这是一个Func委托Func
Join这个返回结果,就是扔进去一个回调函数,在函数体内调用回调函数,左右数据源的项为参数生成新的结果集。最后将回调的结果生成List后返回出来。(这地方就是给不了解委托的读者的一个简单解释。委托就是事先定义好干什么Delegate(参数、返回类型)和调用位置。然后在外面实现一个Delegate的实例 callback 甩进调用过程中)
GroupJoin:基于键值等同性将两个序列的元素进行关联,并对结果进行分组。
GroupJoin
(IEnumerable , IEnumerable , Func , Func , Func ,TResult>, IEqualityComparer )
类型参数
TOuter:第一个序列中的元素的类型。
TInner:第二个序列中的元素的类型。
TKey:键选择器函数返回的键的类型。
TResult:结果元素的类型。
参数
outer:IEnumerable
inner:IEnumerable
outerKeySelector:Func
innerKeySelector:Func
resultSelector:Func
comparer:IEqualityComparer
返回
IEnumerable
参数和Join基本类似,但是多了一个分组,就是如何进行分组和将分组结果装进返回结果中。这里我采用了在结果集中通过Where过滤方式生成分组结果。但我感觉既然GroupJoin就应该不是我采用Where方式分组,还有更简单的方式。如果找到了再就更新。
最后测试了一下,采用Linq比自己写Foreach逻辑块提高速度26%,更重要是代码简洁多了。