C# LINQ入门

记录LINQ学习过程。

概要

LINQ是一种“语言集成”的查询表达式,使用LINQ可以智能提示和进行类型检查。C#里可以编写的LINQ查询有SQL数据库、XML文档、ADO.NET数据集、支持IEnumerable和IEnumerable的对象。使用LINQ,可以简单对数据源进行分组、排序、筛选。有一些第三方库也为Web服务和其他数据库提供了LINQ支持。

数组隐式支持了 IEnumerable 接口的。

//尚未执行查询,等待遍历再查。 可以在查询表达式后面添加ToList或ToArray方法,使之立刻查询。
IEnumerable<int> scoreQuery =           
    from score in new int[] { 97, 92, 81, 60 }
   where score > 90
    select score;

在编译时,查询表达式根据 “C# 规范规则”转换成“标准查询运算符方法调用”。

在编写 LINQ 查询时最好使用查询语法,必要时可以使用方法调用。

查询简介

要想查询,数据源必须在内存中。

//LINQ to XML 将 XML 文档加载到可查询的 XElement 类型中:
XElement contacts = XElement.Load(@"c:\myContactList.xml"); 
//LINQ to SQL ,可以手动设计对象关系映射或借助LINQ TO SQL工具

LINQ和泛型

LINQ引入泛型机制。泛型属于强类型,不必执行运行时类型转换,与Object相比,优势更多。

编译器可以处理泛型类型声明,因此可以通过var关键字避免使用泛型语法。在LINQ里,是否显示指定类型并不重要时,例如LINQ分组查询之后的指定嵌套泛型类型,建议使用var。毕竟晦涩难懂的代码不太招人喜欢喔!

LINQ基本查询

筛选,排序

namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            IEnumerable<Customer> customers = new List<Customer>() {
            new Customer(){Name="David M. Buss" , City="美国奧斯汀"},
            new Customer(){Name="David M. Buss 1" , City="美国奧斯汀"},
            new Customer(){Name="David M. Buss 2" , City="美国奧斯汀"},
            new Customer(){Name="阿尔弗雷德·阿德勒" , City="英国阿伯丁"},};

            var queryUSCustomers = 
                from customer in customers
                where customer.City == "美国奧斯汀"
                orderby customer.Name ascending  
                select customer;

            foreach(var customer in queryUSCustomers)
            {
                Console.WriteLine(customer.Name);
            }
        }
    }
    class Customer
    {
        public string Name { get; set; }
        public string City { get; set; }
    }
}

David M. Buss
David M. Buss 1
David M. Buss 2

 分组

namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            IEnumerable<Customer> customers = new List<Customer>() {
            new Customer(){Name="David M. Buss" , City="美国奧斯汀"},
            new Customer(){Name="David M. Buss 1" , City="美国奧斯汀"},
            new Customer(){Name="David M. Buss 2" , City="美国奧斯汀"},
            new Customer(){Name="阿尔弗雷德·阿德勒" , City="英国阿伯丁"},};

            // queryCustomersByCity is an IEnumerable<IGrouping<string, Customer>>
            var queryCustomersByCity =
                from cust in customers
                group cust by cust.City; //key 就是City

            // customerGroup is an IGrouping<string, Customer>
            //分组类型实现了IEnumerable接口
            foreach (var customerGroup in queryCustomersByCity)
            {
                Console.WriteLine(customerGroup.Key);
                foreach (Customer customer in customerGroup)
                {
                    Console.WriteLine($"    {customer.Name}");
                }
            }
        }
    }
    class Customer
    {
        public string Name { get; set; }
        public string City { get; set; }
    }
}

 关联

namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            IEnumerable<Customer> customers = new List<Customer>() {
            new Customer(){Name="David M. Buss" , City="美国奧斯汀"},
            new Customer(){Name="David M. Buss 1" , City="美国奧斯汀"},           
            new Customer(){Name="阿尔弗雷德·阿德勒" , City="英国阿伯丁"},};

            IEnumerable<City> cities = new List<City>() {
                new City(){Country="美国",CityName="美国奧斯汀"},
                new City(){Country="英国",CityName="英国阿伯丁"},
            };

            var innerJoinQuery =
                from cust in customers
                join city in cities on cust.City equals city.CityName
                select new { Country = city.Country, Customer = cust.Name };
            //匿名类型
          
            foreach (var item in innerJoinQuery)
            {
                Console.WriteLine($"{item.Country},{item.Customer}");               
            }
        }
    }
    class Customer
    {
        public string Name { get; set; }
        public string City { get; set; }
    }
    class City
    {
        public string Country { get; set; }
        public string CityName { get; set; }
    }
}

使用LINQ进行数据转换

可以对原序列修改,可以在返回值创建新类型。

//Concat合并序列
var peopleInSeattle = (from student in students
                         where student.City == "Seattle"
                         select student.Last)
                  .Concat(from teacher in teachers  
                          where teacher.City == "Seattle"
                          select teacher.Last);

//内存中数据结构转换为xml
var studentsToXML = new XElement("Root",
                from student in students
                let scores = string.Join(",", student.Scores) //存储子表达式的结果
                select new XElement("student",
                           new XElement("First", student.First),
                           new XElement("Last", student.Last),
                             new XElement("Scores", GetScore(scores)) //调用C#方法
                        ) // end "student"
                    ); // end "Root"

 支持LINQ的C#功能

string[] stringArray = { "aa", "bb", "b", "a" };
            var query = from str in stringArray
                        group str by str[0] into stringGroup
                        orderby stringGroup.Key
                        select stringGroup;

            foreach (var item in query)
            {
                Console.WriteLine($"key:{item.Key }");
                foreach (var item1 in item)
                {
                    Console.WriteLine(item1);
                }
            }
            //不显示调用构造函数的初始化
            var cust = new Customer { Name = "Mike", Phone = "555-1212" };
            var IncomingOrders = new List<IncomingOrder>();
            var newLargeOrderCustomers = from o in IncomingOrders
                                         where o.OrderSize > 5
                                         select new Customer { Name = o.Name, Phone = o.Phone };
            //等效的方法调用
            var newLargeOrderCustomers1 = IncomingOrders.Where(o => o.OrderSize > 5)
                .Select(y => new Customer { Name = y.Name, Phone = y.Phone });

查询表达式、var、不显示调用构造函数的初始化、匿名类型、扩展方法、lambda表达式。

用C#编写查询LINQ

namespace ConsoleApp4
{
    class Program
    {        
        static void Main(string[] args)
        {
            // studentQuery2 is an IEnumerable<IGrouping<char, Student>>
            IEnumerable<Student> students = new List<Student> { 
                new Student{Last="aa",First="AA"},
                new Student{Last="bb",First="BB"},
                new Student{Last="bcc",First="BCC"}
            };
            
            //创建查询
            var studentQuery=
                from student in students
                group student by student.Last[0];

            //执行查询
            foreach(var item in studentQuery)
            {
                Console.WriteLine($"key:{item.Key}");
                foreach(var item1 in item)
                {
                    Console.WriteLine(item1.Last);
                }
            }

          //使用let引入标识符
           var studentQuery5 =
                from student in students
                let totalScore = student.Scores[0] + student.Scores[1]
                where totalScore / 4 < student.Scores[0]
                select student.Last + " " + student.First; } }
public class Student { public string Last { get; set; } public string First { get; set; } } }

运行结果:
key:a
aa
key:b
bb
bcc

 使用 let 关键字,可以存储表达式结果,存储结果可以提供方便,也可以避免多次计算来提高性能

posted @ 2020-02-22 21:20  舒碧  阅读(580)  评论(0编辑  收藏  举报