c# linq查询语句详细使用介绍
本文介绍Linq的使用方法
linq介绍
LINQ只不过是实现IEnumerable和IQueryable接口的类的扩展方法的集合。
LINQ可以查询IEnumerable集合或者IQueryable数据源
查询语法
List<string> list = new List<string>() { "a", "b", "cb", "d", "e" };
var result = from s in list where s.Contains("b") select s;
方法语法
方法语法的使用就是调用Enumberable或者Queryable的扩展方法
List<string> list = new List<string>() { "a", "b", "cb", "dc", "e" };
var result = list.Where(s => s.Contains("c"));
上面Where中传递的是一个lambda表达式是匿名函数的简写形式,完整写法如下
var result = list.Where(delegate (string s) {
return s.Contains("c");
});
标准的查询操作符
** 过滤操作符
> Where操作符
在查询语句中使用where在后面加上过滤条件(函数)就可以了
List<string> list = new List<string>() { "a", "b", "cb", "dc", "ae" };
Func<string, bool> isFilter = s => s.Contains("a");
var result = from s in list where isFilter(s) select s;
在扩展方法中使用where有两个重载
不带索引的重载
List<string> list = new List<string>() { "a", "b", "cb", "dc", "e" };
var result = list.Where(s => s.Contains("c"));
带索引的重载
List<string> list = new List<string>() { "a", "b", "cb", "dc", "e" };
int isum = 0;
IEnumerable<string> result = list.Where((s, i) =>
{
if (s.Contains("c"))
{
isum++;
return true;
}
return false;
}).ToList(); // 这里不写ToList()的话linq语句不执行
return Ok(isum);
无论是查询语句还是扩展方法,where都可以使用多个
IEnumerable<string> result = list.Where(s => s.Contains("c")).Where(s => s.Contains("b"));
> OfType操作符
使用OfType操作符可以根据数据类型来过滤数据
在查询语句中使用
ArrayList list = new ArrayList() { 2, "a", 5};
var result = from s in list.OfType<int>() select s; // 将ArrayList所有的int类型数据筛选出来
在扩展方法中使用
ArrayList list = new ArrayList() { 2, "a", 5};
var result = list.OfType<string>();
** 排序操作符
> OrderBy语句
根据指定的字段升序或者降序排序
IList<TestClass> list = new List<TestClass>() {
new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
new TestClass() { StudentID = 2, StudentName = "Steve", Age = 15 } ,
new TestClass() { StudentID = 3, StudentName = "Bill", Age = 15 } ,
new TestClass() { StudentID = 4, StudentName = "Ram" , Age = 20 } ,
new TestClass() { StudentID = 5, StudentName = "Ron" , Age = 19 }
};
在查询语句中使用
var result = from s in list orderby s.Age select s; // 默认是升序排序,ascending可以指定也可以不写
var result = from s in list orderby s.Age descending select s; // 指定descending实现降序
可以指定多条列进行排序
var result = from s in list orderby s.Age, s.StudentID descending select s;
如果s.Age是相同的,那么根据s.StudentID对相同的数据进行排序
在扩展语句中使用
重载一,使用默认规则实现简单的升序排序
var result = list.OrderBy(s => s.Age); // 根据Age字段进行升序排序,不支持降序
重载二,可以传递IComparer泛型实例,实现自定义排序规则
先定义一个实现IComparer的类
public class CompareClass : IComparer<string>
{
public int Compare(string x, string y)
{
string str1 = x.Substring(1, 1);
string str2 = y.Substring(1, 1);
return int.Parse(str1).CompareTo(int.Parse(str2)); // 升序,如果调换str1和str2的位置,可以实现降序
}
}
实现排序
IList<TestClass> list = new List<TestClass>() {
new TestClass() { StudentID = 1, StudentName = "A3_John", Age = 18 } ,
new TestClass() { StudentID = 2, StudentName = "A4_Steve", Age = 15 } ,
new TestClass() { StudentID = 3, StudentName = "A2_Bill", Age = 25 } ,
new TestClass() { StudentID = 4, StudentName = "A5_Ram" , Age = 20 } ,
new TestClass() { StudentID = 5, StudentName = "A6_Ron" , Age = 19 }
};
var result = list.OrderBy(s => s.StudentName, new CompareClass());
> OrderByDescending语句
根据指定的字段降序排序,只能在扩展方法中使用
var result = list.OrderByDescending(s => s.Age);
> ThenBy语句
用于二级排序的升序,只能在扩展方法中使用
var result = list.OrderBy(s => s.Age).ThenBy(s => s.StudentID);
对s.Age排序后的结果中的相同项按照s.StudentID进行升序排序
> ThenByDescending语句
用于二级排序的降序,只能在扩展方法中使用
var result = list.OrderBy(s => s.Age).ThenByDescending(s => s.StudentID);
对s.Age排序后的结果中的相同项按照s.StudentID进行降序排序
> Reverse语句
反序排序,只能用于扩展方法中
var result = list.Reverse();
对原始集合进行反转排序操作
** 分组操作符
> GroupBy操作符
GroupBy根据指定的列将相同项分成一组,返回的结果是IEnumerable <IGrouping<TKey, TSource>>类型
每组是IGrouping<TKey, TSource>类型,TKey是键的类型,TSource是结果集合的类型
IList<TestClass> list = new List<TestClass>() {
new TestClass() { StudentID = 1, StudentName = "A3_John", Age = 18 } ,
new TestClass() { StudentID = 2, StudentName = "A4_Steve", Age = 15 } ,
new TestClass() { StudentID = 3, StudentName = "A2_Bill", Age = 15 } ,
new TestClass() { StudentID = 4, StudentName = "A5_Ram" , Age = 20 } ,
new TestClass() { StudentID = 5, StudentName = "A6_Ron" , Age = 20 }
};
在查询语句中使用
var result = from s in list group s by s.Age;
foreach(var ageGroup in result)
{
Trace.WriteLine(ageGroup.Key); // Key是分组的Age值
foreach( TestClass s in ageGroup)
{
// ...
}
}
在扩展方法中使用
var result = list.GroupBy(s => s.Age);
> ToLookup操作符
只能在扩展方法中使用
var result = list.ToLookup(s => s.Age);
ToLookup和GroupBy功能是一样的,但是ToLookup是立即执行的,而GroupBy之后的result是没有值的,只会在使用的时候执行并存储数据
** 连接操作符
> Join操作符
作用和sql的 inner Join 一样
在扩展方法中使用
例子一:
第一个参数是inner表,第二个参数是outer表的列,第三个参数是inner表的列,第四个参数是结果集的格式
当第二个参数和第三个参数对应的列值相同,那么数据筛选出来,然后经过第四个参数处理后返回
List<string> list1 = new List<string>() { "a", "b", "c", "d", "e" };
List<string> list2 = new List<string>() { "a", "b", "e", "f", "a" };
var result = list1.Join(list2, s1 => s1, s2 => s2, (s1, s2) => s1);
例子二:
IList<Demo1> studentList1 = new List<Demo1>() {
new Demo1() { StudentID = 1, StudentName = "John", StandardID =1 },
new Demo1() { StudentID = 2, StudentName = "Moin", StandardID =1 },
new Demo1() { StudentID = 3, StudentName = "Bill", StandardID =2 },
new Demo1() { StudentID = 4, StudentName = "Ram" , StandardID =2 },
new Demo1() { StudentID = 5, StudentName = "Ron" }
};
IList<Demo2> standardList2 = new List<Demo2>() {
new Demo2(){ StandardID = 1, StandardName="Standard 1"},
new Demo2(){ StandardID = 2, StandardName="Standard 2"},
new Demo2(){ StandardID = 3, StandardName="Standard 3"}
};
var result = studentList1.Join(standardList2, s1 => s1.StandardID, s2 => s2.StandardID, (s1, s2) =>
{
return new
{
StudentName = s1.StudentName,
StandardName = s2.StandardName
};
});
在查询语句中使用
使用上面的studentList1和standardList2为例
var result = from s1 in studentList1
join s2 in standardList2 on s1.StandardID equals s2.StandardID
select new
{
StudentName = s1.StudentName,
standardName = s2.StandardName
};
> GroupJoin操作符
作用和sql的 left join,right join类似
在扩展方法中使用
还是使用上面的studentList1和standardList2为例
var result = studentList1.GroupJoin(standardList2, s1 => s1.StandardID, s2 => s2.StandardID, (s1, s2Obj) =>
{
return new
{
studentName = s1.StudentName,
standardName = s2Obj // s2Obj自动将 s2 转成 IEnumerable类型
};
});
在查询语句中使用
var result = from s1 in studentList1
join s2 in standardList2 on s1.StandardID equals s2.StandardID into s3
select new
{
standard = s3,
studentName = s1.StudentName
};
** 投影操作符
> select操作符
和sql中的select类似
在查询语句中使用
var result = from item in someList select item;
var result = from item in someList select new { column1 = item.Name, column2 = item.Age };
在扩展方法中使用
在扩展方法中Select方法仅仅用来格式化数据,在查询数据时是可选项
var result = list.Select(s => new
{
Name = s.StudentName,
Age = s.Age
});
> SelectMany方法
SelectMany方法只能在扩展方法中使用
SelectMany的作用是将指定列对应的IEnumerable列值合并成一个集合,用法如下
定义两个类
public class Students
{
public string Name { get; set; }
public int Age { get; set; }
}
public class ClassNames
{
public IEnumerable<Students> students { get; set; }
public string Name { get; set; }
}
使用SelectMany
List<ClassNames> selectManyTest = new List<ClassNames>() { };
selectManyTest.Add(new ClassNames() { students = new List<Students>() { new Students() { Name = "小张", Age = 11 } }, Name = "班级一" });
selectManyTest.Add(new ClassNames() { students = new List<Students>() { new Students() { Name = "小王", Age = 21 } }, Name = "班级二" });
selectManyTest.Add(new ClassNames() { students = new List<Students>() { new Students() { Name = "小红", Age = 22 } }, Name = "班级三" });
var result = selectManyTest.SelectMany(s => s.students);
result的结果 [{"Name":"小张","Age":11},{"Name":"小王","Age":21},{"Name":"小红","Age":22}]
这种用法其实和Select的作用是一致的 var result = selectManyTest.Select(s => s.students); 关键是下面的这种用法
var result = selectManyTest.SelectMany(s => s.students, (s1, s2) =>
{
return new
{
班级名称 = s1.Name,
学生姓名 = s2.Name,
学生年龄 = s2.Age
};
});
结果是 [{"班级名称":"班级一","学生姓名":"小张","学生年龄":11},{"班级名称":"班级二","学生姓名":"小王","学生年龄":21},{"班级名称":"班级三","学生姓名":"小红","学生年龄":22}]
从这里可以看出SelectMany的优势是将嵌套的复杂类型综合到一个集合中
** 量词操作符
IList<TestClass> studentList = new List<TestClass>() {
new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
new TestClass() { StudentID = 2, StudentName = "Steve", Age = 15 } ,
new TestClass() { StudentID = 3, StudentName = "Bill", Age = 25 } ,
new TestClass() { StudentID = 4, StudentName = "Ram" , Age = 20 } ,
new TestClass() { StudentID = 5, StudentName = "Ron" , Age = 19 }
};
> ALL操作符
指定筛选条件如果元素全部满足则返回true
bool result = studentList.All(s => s.Age > 18 && s.Age < 20); // false
> Any操作符
指定筛选条件只要有一个满足就返回true
bool result = studentList.Any(s => s.Age > 18 && s.Age < 20); // true
> Contains操作符
值类型用法
List<int> list = new List<int>() { 1, 2, 3, 4, 5 };
bool result = list.Contains(4);
引用类型用法
引用类型默认比较的是引用,如果要实现自定义比较引用类型,就要实现一个IEqualityComparer类
创建一个IEqualityComparer类
public class StudentComparer : IEqualityComparer<TestClass>
{
public bool Equals(TestClass x, TestClass y)
{
if (x.StudentID == y.StudentID &&
x.StudentName.ToLower() == y.StudentName.ToLower() &&
x.Age == y.Age)
{
return true;
}
return false;
}
public int GetHashCode(TestClass obj)
{
Trace.WriteLine(obj.GetHashCode());
return obj.GetHashCode();
}
}
使用
bool result = studentList.Contains(new TestClass() { StudentID = 2, StudentName = "Steve", Age = 15 }, new StudentComparer()); // true
** 聚合操作符
在linq中聚合函数不能直接使用在查询语句中,但是可以像下面这种方式使用
var result = (from s in studentList where s.Age > 20 select s).Average(s => s.Age);
> Aggregate操作符
用来累积结果
重载一
List<string> list = new List<string> { "a", "b", "c", "d" };
var result = list.Aggregate((s1, s2) =>
{
return s1 + s2;
}); // "abcd"
重载二,需要一个seed作为初始值
List<string> list = new List<string> { "a", "b", "c", "d" };
var result = list.Aggregate("结果是:", (s1, s2) =>
{
return s1 + s2;
}); // "结果是:abcd"
重载三,需要一个Func代理函数用来对计算的结果做处理
List<string> list = new List<string> { "a", "b", "c", "d" };
var result = list.Aggregate(String.Empty, (s1, s2) =>
{
return s1 += s2 + ",";
}, res => res.Substring(0, res.Length - 1)); // "a,b,c,d"
> Average操作符
用来计算集合中的数字值的平均值
计算由数字组成的集合的平均值
List<int> list = new List<int>() { 1, 2, 3, 4, 5 };
var result = list.Average();
传递lambda表达式,用来计算引用类型中的数字的平均值
var result = studentList.Average(s => s.Age);
> Count操作符
返回集合的元素的个数
var result = studentList.Count();
返回满足给定条件的元素个数
var result = studentList.Count(s => s.Age > 19);
> Max操作符
返回数字集合的最大值
List<int> list = new List<int>() { 1, 2, 3, 7, 4, 5, 6 };
var result = list.Max(); // 最大值 7
var result = list.Max(s => s * 2); // 将元素乘2后计算最大值,14
返回引用类型集合数字属性的最大值
var result = studentList.Max(s => s.Age);
对于引用类型可以实现自定义的Max比较
先声明一个类,实现了 IComparable 接口
public class TestClass: IComparable<TestClass>
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public int Age { get; set; }
public int CompareTo(TestClass other) // 用来筛选出StudentName长度最长的一项
{
if(this.StudentName.Length >= other.StudentName.Length)
{
return 1;
}
return 0;
}
}
使用
IList<TestClass> studentList = new List<TestClass>() {
new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
new TestClass() { StudentID = 2, StudentName = "Steve", Age = 15 } ,
new TestClass() { StudentID = 3, StudentName = "Bill", Age = 25 } ,
new TestClass() { StudentID = 4, StudentName = "Ram" , Age = 20 } ,
new TestClass() { StudentID = 5, StudentName = "Ron" , Age = 19 }
};
var result = studentList.Max(); // 直接调用Max即可
Min的使用方式和Max是一直的,不再赘述
> Sum操作符
返回数字集合的总和
List<int> list = new List<int>() { 1, 2, 3, 7, 4, 5, 6 };
var result = list.Sum(); // 返回总和
var result = list.Sum(s => s * 2 + 1); // 返回每一项乘2加1后的总和
返回应用类型集合数字属性的总和
var result = studentList.Sum(s => s.Age); // 计算年龄的总和
var result = studentList.Sum(s => {
if(s.Age > 18)
{
return 1;
}
return 0;
}); // 计算年龄大于18的人数
** 元素操作符
List<int> intList = new List<int>() { 10, 21, 30, 45, 50, 87 };
> ElementAt操作符
根据索引找出元素,超出范围会报错
var result = intList.ElementAt(1);
> ElementAtOrDefault操作符
根据索引找出元素,超出范围返回默认值,整数默认值是0,字符串默认值是null
var result = intList.ElementAtOrDefault(9);
> First操作符
返回第一个元素或者第一个满足条件的元素,如果给定的集合是空的,或者没有一个元素满足条件,那么会报错
var result = intList.First(); // 返回集合中的第一个元素
var result = intList.First(s => s > 30); // 返回满足条件的第一个元素
Last的用法和First一致
> FirstOrDefault操作符
返回第一个元素或者第一个满足条件的元素,如果给定的集合是空的,或者没有一个元素满足条件那么返回默认值
用法和上面一样
LastOrDefault的用法和FirstOrDefault一致
> Single操作符
返回集合中的唯一一个元素,或者指定条件后唯一一个元素,如果没有元素或者多于一个元素那么报错
List<int> intList = new List<int>() { 10 };
var result = intList.Single();
> SingleOrDefault操作符
作用和Single类似,如果没有找到元素,那么返回默认值,然而,如果有多个元素那么同样报错
List<int> intList = new List<int>() { 10,20 };
var result = intList.SingleOrDefault(s => s > 10);
** 相等运算符
> SequenceEqual
用于比较两个集合中的元素是否相等,如果元素是值类型,那么比较元素的值和顺序,如果是引用类型那么比较值的引用
值类型比较
List<int> intList1 = new List<int>() { 10,20 };
List<int> intList2 = new List<int>() { 10, 20 };
var result = intList1.SequenceEqual(intList2); // true
引用类型比较
List<TestClass> TestList1 = new List<TestClass>() { new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } };
List<TestClass> TestList2 = new List<TestClass>() { new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } };
var result = TestList1.SequenceEqual(TestList2); // false
自定义引用类型比较
如果不想比较引用类型的时候比较引用地址,那么可以使用自定义比较
首先,创建一个实现了IEqualityComparer接口的类
private class SequenceEqualComparer : IEqualityComparer<TestClass>
{
public bool Equals(TestClass x, TestClass y)
{
if(x.StudentID == y.StudentID && x.StudentName == y.StudentName && x.Age == y.Age)
{
return true;
}
return false;
}
public int GetHashCode(TestClass obj)
{
return obj.GetHashCode();
}
}
使用
List<TestClass> TestList1 = new List<TestClass>() { new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } };
List<TestClass> TestList2 = new List<TestClass>() { new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } };
var result = TestList1.SequenceEqual(TestList2, new SequenceEqualComparer()); // true
** 串联运算符
> Concat运算符
用于连接两个集合
var result = TestList1.Concat(TestList2);
** 生成运算符
> DefaultIfEmpty操作符
如果调用此方法的集合是空的则返回一个新的集合,新集合包含一个默认值元素
不指定默认值
List<string> list = new List<string>();
var result = list.DefaultIfEmpty(); // 结果 [null]
指定默认值
var result = list.DefaultIfEmpty("haha"); // 结果 ["haha"]
本质
DefaultIfEmpty本质作用是将一个集合拷贝了一份,如果集合是空的自动填充一个默认值
List<string> list = new List<string>() { "a" };
var temp = list.DefaultIfEmpty("haha");
var result = temp == list; // false
> Empty, Range, Repeat 操作符
这三个运算符不是IEnumerable 和 IQueryable的扩展方法,而是Enumerable的静态方法
Empty操作符
返回一个空的集合
var result = (Enumerable.Empty<string>()).GetType().Name; // "String[]"
Range操作符
返回一个集合,元素从指定的数字开始,按照指定的个数依次递增
var result = Enumerable.Range(10, 10); // [10,11,12,13,14,15,16,17,18,19]
Repeat操作符
返回一个集合,元素是指定个数的相同的指定元素
var result = Enumerable.Repeat<string>("a", 10); // ["a","a","a","a","a","a","a","a","a","a"]
** 集操作符
> Distinct
取出集合中重复项,并返回一个新的集合
对值类型集合的操作
List<string> list = new List<string>() { "a", "b", "c", "d", "b", "c" };
var result = list.Distinct(); // ["a","b","c","d"]
对引用类型集合的操作,默认无效,需要自己实现IEqualityComparer类
首先实现IEqualityComparer类
Equals,GetHashCode方法会自动调用,当GetHashCode返回的整数(引用)不一致,那么会执行Equals方法
private class DistinctComparer : IEqualityComparer<TestClass>
{
public bool Equals(TestClass x, TestClass y)
{
if(x.StudentID == y.StudentID && x.StudentName == y.StudentName && x.Age == y.Age)
{
return true;
}
return false;
}
public int GetHashCode(TestClass obj)
{
return obj.StudentID.GetHashCode(); // 注意,表示如果 StudentID的GetHashCode 相同,那么过滤掉这个数据
}
}
使用
List<TestClass> studentList = new List<TestClass>() {
new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
new TestClass() { StudentID = 2, StudentName = "Steve", Age = 15 }
};
var result = studentList.Distinct(new DistinctComparer());
> Except
返回一个新的集合,集合的成员是list1在list2中不存在的元素
对值类型集合的操作
List<string> list1 = new List<string>() { "a", "b", "c" };
List<string> list2 = new List<string>() { "c", "d", "a" };
var result = list1.Except(list2); // ["b"]
对引用类型集合的操作,同样也要自己实现IEqualityComparer类
创建一个IEqualityComparer类,和上面一模一样
private class ExceptComparer : IEqualityComparer<TestClass>
{
public bool Equals(TestClass x, TestClass y)
{
if (x.StudentID == y.StudentID && x.StudentName == y.StudentName && x.Age == y.Age)
{
return true;
}
return false;
}
public int GetHashCode(TestClass obj)
{
return obj.StudentID.GetHashCode(); // 注意,表示如果 StudentID的GetHashCode 相同,那么过滤掉这个数据
}
}
使用
List<TestClass> studentList1 = new List<TestClass>() {
new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
new TestClass() { StudentID = 2, StudentName = "Steve", Age = 15 }
};
List<TestClass> studentList2 = new List<TestClass>() {
new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
new TestClass() { StudentID = 3, StudentName = "John", Age = 18 } ,
new TestClass() { StudentID = 4, StudentName = "Steve", Age = 15 }
};
var result = studentList1.Except(studentList2, new ExceptComparer()); // [{"StudentID":2,"StudentName":"Steve","Age":15}]
> Intersect
相当于取交集
值类型集合操作
List<string> list1 = new List<string>() { "a", "b", "c" };
List<string> list2 = new List<string>() { "c", "d", "a" };
var result = list1.Intersect(list2); // ["a","c"]
引用类型集合操作,同样也是要创建IEqualityComparer类,实现和上面是一模一样,不再赘述
使用
var result = studentList1.Intersect(studentList2, new IntersectComparer());
// 返回结果 [{"StudentID":1,"StudentName":"John","Age":18}]
> Union
将两个集合拼接起来,并且剔除掉重复项
值类型集合操作
List<string> list1 = new List<string>() { "a", "b", "c", "a", "b" };
List<string> list2 = new List<string>() { "c", "d", "a" };
var result = list1.Union(list2); // ["a","b","c","d"]
引用类型集合操作,同样也是要创建IEqualityComparer类,实现和上面是一模一样,不再赘述
使用
var result = studentList1.Union(studentList2, new UnionComparer());
返回结果如下
/*
[
{"StudentID":1,"StudentName":"John","Age":18},
{"StudentID":2,"StudentName":"Steve","Age":15},
{"StudentID":3,"StudentName":"John","Age":18},
{"StudentID":4,"StudentName":"Steve","Age":15}
]
*/
** 分区操作符
> Skip操作符
过滤掉集合中指定个数的元素,返回剩余元素组成的集合
List<string> list = new List<string>() { "a", "b", "c" };
var result = list.Skip(2); // ["c"]
> SkipWhile操作符
指定条件过滤,如果条件满足全部过滤掉,直到条件为false,返回剩余元素组成的集合
List<int> list = new List<int>() { 1, 2, 5, 2, 4, 5, 6 };
var result = list.SkipWhile((s, i) => s < 3); // [5,2,4,5,6]
> Take操作符
功能和Skip相反,获取指定数量的元素,并返回新的集合
List<string> list = new List<string>() { "a", "b", "c" };
var result = list.Take(2); // ["a","b"]
> TakeWhile操作符
功能和SkipWhile相反,获取满足指定条件的元素,直到条件不满足,返回新的集合
List<int> list = new List<int>() { 1, 2, 5, 2, 4, 5, 6 };
var result = list.TakeWhile((s, i) => s < 3); // [1,2]
** 转换运算符
> AsEnumerable操作符
将集合强制转换成IEnumerable集合
int[] arr = new int[] { 1, 2, 3, 4, 5 };
var result = arr.AsEnumerable();
> AsQueryable操作符
将集合强制转换成IQueryable集合
List<int> list = new List<int>() { 1, 2, 5, 2, 4, 5, 6 };
var result = list.AsQueryable();
> Cast操作符
作用和AsEnumerable是一样的
int[] arr = new int[] { 1, 2, 3, 4, 5 };
var result = arr.Cast<int>(); 等效于 var result = (IEnumerable<int>)arr;
> ToArray,ToList,ToDictionary扩展方法
To系列的操作,会强制让sql语句执行结果并且将数据缓存在本地
int[] arr = new int[] { 1, 2, 3, 4, 5 };
ToArray使用
int[] result = arr.ToArray<int>();
ToList使用
List<int> result = arr.ToList<int>();
ToDictionary使用
var result = arr.ToDictionary<int, int>(s => s);
Linq中的Expression类型
由Func和Action类型的委托构建的lambada表达式在编译期间会转换成可执行的代码,linq引入新的Expression类型,将lambda表达式转换成Expression树而不是可执行代码
传统写代理的方式
Func<int, bool> isTest = s => s > 5;
Expression写代理的方式
Expression<Func<int, bool>> isTest = s => s > 5;
调用Expression代理
调用之前需要先编译一下
Func<int, bool> isIWant = isTest.Compile();
bool result = isIWant(3);
为什么要有表达式树?
编译的区别
Func编译后的代码 {Method = {Boolean <.ctor>b__9_0(Int32)}}
Expression编译后的代码 {s => (s > 5)}
很明显的感觉到,Func编译后被改了,表达式树更加的透明,你可以轻松的调用Expression的方法访问方法的每一个部分
处理代码的区别
Func值适合当前程序集中运行,也就是说只适合内存中的集合,因为如果涉及数据库查询的话,数据库无法获知编译后的IL代码到底是个啥
Expression表达式树,专门用来处理类似数据库的操作
执行效率
Func要想操作数据库,需要借助Entity Frameworks将可执行代码编译成Sql查询字符串发送到sql server数据库中
使用Expression表达式树,可以轻松的将lambda表达式转换成Sql语句,因为Expression内置了很多属性和方法方便获取表达式的每一部分,所以执行效率更快
总之,一句话,操作数据库使用Expression更好
延迟执行linq查询
linq表达式不会立即执行,而是用到了才会调用,从而保证每次使用linq时都是最新的数据
默认情况下linq的延迟加载不会有什么特殊的效果,只是简单的延迟而已,但是你可以自定义扩展方法使用yield关键字实现自己的延迟效果
首先,要定义扩展方法,需要一个顶级静态类
public static class EnumerableExtensionMethodsDemo
{
public static IEnumerable<int> GetIWant(this List<int> test)
{
foreach (int item in test)
{
if(item > 5 && item < 10)
{
yield return item;
}
}
}
}
使用
List<int> list = new List<int>() { 1, 2, 10, 50, 30, 5, 7, 9, 11 };
var result = from s in list.GetIWant() select s;
foreach (int i in result)
{
// 在这里才会调用result查询语句
}
立即执行linq查询
上面讲到的以to开头的扩展方法,都可以让linq语句立即执行
linq中使用let关键字
List<string> list = new List<string>() { "sa", "rb", "bc", "sd" };
var result = from s in list where s.ToLower().StartsWith("s") select s.ToLower();
上面这个查询语句中 ToLower 使用了两次,很啰嗦,可以使用let简化
var result = from s in list
let lowerItem = s.ToLower()
where lowerItem.StartsWith("s")
select lowerItem;
into关键字
into关键字单独使用的作用,是将上个查询语句的结果传递到下一个查询语句中,两个查询语句中的变量互不影响
List<string> list = new List<string>() { "sa", "rb", "bc", "sd" };
var result = from s in list
where s.ToLower().StartsWith("s")
select s
into s
where s.ToLower().EndsWith("a")
select s; // ["sa"]
c# linq查询语句详细使用介绍的更多相关文章
- 简单的Linq查询语句
下面我来我大家介绍几种简单的查询方式. 1.简单语法 这个LINQ语句的第一个关键字是from,from后面加的是范围变量,范围变量后加in,后加上事先实例化的模型,然后点出数据的来源. List是列 ...
- linq查询语句转mongodb
&& (与操作) 子表达式可以通过&&合并来查询满足所有子表达式的文档 var query = from c in collection.AsQueryable< ...
- C#高级知识点概要(3) - 特性、自动属性、对象集合初始化器、扩展方法、Lambda表达式和Linq查询
1.特性(Attributes) 特性(Attributes),MSDN的定义是:公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法 ...
- C# LINQ查询表达式用法对应Lambda表达式
C#编程语言非常优美,我个人还是非常赞同的.特别是在学习一段时间C#后发现确实在它的语法和美观度来说确实要比其它编程语言强一些(也可能是由于VS编译器的加持)用起来非常舒服,而且对于C#我觉得他最优美 ...
- 【总结】LINQ查询基本操作列表
每个LINQ查询都以from子句开始,from子句包括以下两个功能. 指定查询将采用数据源. 定义一个本地变量,表示数据源中单个元素. string[] values = { "中国&quo ...
- LINQ中的一些查询语句格式
LINQ的基本格式如下所示:var <变量> = from <项目> in <数据源> where <表达式> orderby <表达式> ...
- 浅谈sql 、linq、lambda 查询语句的区别
浅谈sql .linq.lambda 查询语句的区别 LINQ的书写格式如下: from 临时变量 in 集合对象或数据库对象 where 条件表达式 [order by条件] select 临时变量 ...
- ES 常用的查询语句介绍
elasticsearch定义了两种查询方式: 一.索引(index).type.document 相关语句 1.列出所有索引的状态 GET /_cat/indices?v health status ...
- 这里我们介绍的是 40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询。这些是所有 Oracle 开发者都必备的技能,所以快快收藏吧!
日期/时间 相关查询 获取当前月份的第一天 运行这个命令能快速返回当前月份的第一天.你可以用任何的日期值替换 “SYSDATE”来指定查询的日期. SELECT TRUNC (SYSDATE, 'MO ...
随机推荐
- springcloud一些概念知识
1.Eureka 1)Eureka服务治理体系支持跨平台 2)三个核心概念:服务注册中心.服务提供者以及服务消费者 3)服务续约:注册完服务之后,服务提供者会维护一个心跳来不停的告诉Eureka Se ...
- SpringCloud-路由网关(Zuul)
在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.只能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统. 在Spring Cloud ...
- 介绍一下Hibernate的二级缓存
介绍一下Hibernate的二级缓存 按照以下思路来回答:(1)首先说清楚什么是缓存,(2)再说有了hibernate的Session就是一级缓存,即有了一级缓存,为什么还要有二级缓存,(3)最后再说 ...
- pf_ring DNA接收流程代码分析
经过一个月的学习,对pf_ring DNA的内核部分有了一些认识,本文侧重pf_ring对ixgbe的改动分析. 先说一说接收流程吧,流程如下: 其中,硬中断处理函数是ixgbe_msix_clean ...
- HTML中table边框的显示总结
一.1.显示表格的4个边框:<table border frame=box>2.只显示上边框: <table border frame=above>3.只显示下边框: < ...
- Elasticsearch Suggester 学习
suggester搜索就像百度搜索框中的提示类似. Elasticsearch 中提供类似的搜索功能. 答案就在Suggesters API. Suggesters基本的运作原理是将输入的文本分解为t ...
- review35
使用Thread创建线程通常使用的方法是:Thread(Runnable target).该构造方法中的参数是一个Runnable类型的接口,因此在创建线程对象时必须向构造方法的参数传递一个实现Run ...
- python中的excel操作
一. Excel在python中的应用 存测试数据 有的时候大批量的数据,我们需要存到数据库中,在测试的时候才能用到.测试的时候就从数据库中读取出来.这点是非常重要的! 存测试结果 二. Excel中 ...
- AI探索(四)NumPy库的使用
NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库. umPy 是一个运行速度非常快的数学库, ...
- eclipse部署和启动guns
eclipse部署guns: 1.import -> 搜索maven -> Existing Maven Projects -> 选择guns根目录 2.修改配置文件: spring ...