C#编程之Linq查询

作者:陆金龙    发表时间:2015-06-22 15:14   


1.Linq查询

Linq 查询可针对 Object,XML,SQL进行,查询语法基本相同。

1.1 Linq To Object

List<Product> products =Product.GetData();

List<Supplier> suppliers=Supplier.GetData();

var objs = from p in products

   join s in suppliers

              on p.SupplierId equals s.SupplierId

           where p.Price>10

           order by s.Name,p.Name

           select new{SupplierName=s.Name,ProductName=p.Name};

foreach(var obj in objs)

{

Console.WriteLine(“{0},{1}”,obj.SupplierName,obj.ProductName);

}

按名称排序和过滤重复数据:

List<Product> productsNew = (from product in products select product).OderBy< Product (p=>p.Name).Distinct().ToList();

1.2 Linq To XML

1)data.xml文档内容

<?xml version=”1.0”?>

<Data>

<products >

<product Name=”West” Price=”9.99” SupplierId=”1” />

<product Name=”Frogs” Price=”13.99” SupplierId=”3” />

</products >

<suppliers >

<supplier Name=”Solely” SupplierId=”1” />

<supplier Name=”Barber” SupplierId=”2” />

<supplier Name=”Tom” SupplierId=”3” />

</suppliers >

</Data>

 

2)Linq To Xml 查询

Xdocument doc = Xdocument.Load(“data.xml”);

var objs = from p in doc.Decendants(“products”);

   join s in doc.Decendants(“suppliers”);

              on (int)p.Attribute(“SupplierId”) equals (int)s.Attribute(“SupplierId”)

           where (decimal)p.Attribute(“Price”)>10

           order by (string)s.Attribute(“Name”),(string)p.Attribute(“Name”)

           select new{SupplierName=(string)s.Attribute(“Name”),ProductName=(string)p.Attribute(“Name”)

};

foreach(var obj in objs)

{

Console.WriteLine(“{0},{1}”,obj.SupplierName,obj.ProductName);

}

3) Linq To XML应用:数据库连接工具

主要功能:

1)获取数据库连接设置,显示到界面。

2)测试数据库连接是否成功

3)修改和保存数据库连接设置

代码清单:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Xml.Linq;

using System.Configuration;

using System.Text.RegularExpressions;

using System.Data.SqlClient;

 

namespace WindowsFormsApplication1

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        string connstr = null;

        /// <summary>

        /// 加载窗体,显示配置文件中的连接字符串数据到文本框

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void Form1_Load(object sender, EventArgs e)

        {

            string connTemp = null;

            XDocument xdoc = XDocument.Load("LinqToXml_EditApp.exe.config");

            var query = from conn in

                            (from ele in xdoc.Descendants()

                             where ele.Name == "connectionStrings"

                             select ele).Elements()

                        where conn.Attribute("name").Value == "sql" 

                        select conn.Attribute("connectionString").Value;

 

            var temp = query.GetEnumerator();

            if (temp.MoveNext())

            {

                //得到连接字符串

                connTemp = temp.Current;

                //分割得到连接字符串各参数的值

                List<string> list = new List<string>();

                string[] strs = connTemp.Split(';');

                for (int i = 0; i < 4; i++)

                {

                    list.Add(strs[i].Split('=')[1].Trim());

                }

                //给文本框赋值

                textServer.Text = list[0];

                textDatabase.Text = list[1];

                textUser.Text = list[2];

                textPass.Text = list[3];

            } 

        }

        /// <summary>

        /// 测试数据库连接

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void button1_Click(object sender, EventArgs e)

        {

            //拼接得到连接字符串

            string server = textServer.Text.Trim();

            string database = textDatabase.Text.Trim();

            string uid = textUser.Text.Trim();

            string pwd = textPass.Text.Trim();

            if (string.IsNullOrEmpty(server) || string.IsNullOrEmpty(database) || string.IsNullOrEmpty(uid) || string.IsNullOrEmpty(pwd))

            {

                MessageBox.Show("输入不能为空!");

                return;

            }

            connstr = "server = " + server + ";database = " + database + ";uid = " + uid + ";pwd = " + pwd;

            using (SqlConnection conn = new SqlConnection(connstr))

            {

                conn.Close();

                try

                {

                    conn.Open();

                    MessageBox.Show("连接成功!");

                }

                catch (Exception)

                {

                    MessageBox.Show("连接失败!");

                }

            }

        }

        /// <summary>

        /// 保存新的连接字符串数据到配置文件

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void button2_Click(object sender, EventArgs e)

        {    

           //拼接得到连接字符串

           string server= textServer.Text.Trim() ;

           string database = textDatabase.Text.Trim() ;

           string uid = textUser.Text.Trim();

           string pwd = textPass.Text.Trim();

           if (string.IsNullOrEmpty(server)||string.IsNullOrEmpty(database)||string.IsNullOrEmpty(uid)||string.IsNullOrEmpty(pwd))

       {

        MessageBox.Show("输入不能为空!");

                return;

       }

           connstr = "server = " + server + ";database = " + database + ";uid = " + uid + ";pwd = " + pwd;

           //用LinqToXml读取app文件

           XDocument xdoc = XDocument.Load("LinqToXml_EditApp.exe.config");

 

           //获取connectionStrings元素

           var conns = from conn in xdoc.Descendants()

                       where conn.Name == "connectionStrings"

                       select conn ;

           //创建枚举器,获取第一个add节点

   //<add name="conString" connectionString="Data Source=.;Initial Catalog=lyncplus2013;user id =lyncplus;password=lyncplus"/>

           var enumtor=conns.Elements().GetEnumerator();

           enumtor.MoveNext();

           XElement addNode= (XElement)enumtor.Current;

 

           //修改属性值,更新xdoc到配置文件

           addNode.LastAttribute.SetValue(connstr);

           xdoc.Save("LinqToXml_EditApp.exe.config");

           MessageBox.Show("保存成功");

        }

    }

}

1.3 Linq To SQL

1)DataContext

查询是用C#代码来表示的,但是却是由SQL来执行的。

DataContext类型(数据上下文)是System.Data.Linq命名空间下的重要类型,用于把查询句法翻译成SQL语句,以及把数据从数据库返回给调用方和把实体的修改写入数据库。LinqDemoDataContext db = new LinqDemoDataContext();

2)Linq To SQL 查询

using(LinqDemoDataContext db = new LinqDemoDataContext())

{

var objs = from p in db.Products

   join s in db.Suppliers

              on p.SupplierId equals s.SupplierId

           where p.Price>10

           order by s.Name,p.Name

           select new{SupplierName=s.Name,ProductName=p.Name};

foreach(var obj in objs)

{

Console.WriteLine(“{0},{1}”,obj.SupplierName,obj.ProductName);

}

}

 

2.Linq查询应用详解

2.0 基本步骤

     //  1. LINQ查询第一步,获取数据源.

     int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

     

     // 2. LINQ查询第二步,定义查询numQuery 是 IEnumerable<int>泛型

     var numQuery =

          from num in numbers

          where (num % 2) == 0

          orderby num descending

          select num;

     

     // 3. LINQ查询第三步执行查询.

      foreach (int num in numQuery)

      {

          Console.Write("{0,1} ", num);

      }

      Console.Read ();

2.1 查询数组

2.1.1 查询数组

        static void Main(string[] args)

        {

            //声明一个有6个元素的字符串数组names

            string[] names = { "Everett", "Albert", "George", "Harris", "David" };

            var items = from name in names  //声明一个匿名变量items,使用LINQ在数组names中找出长度

                        where name.Length >= 6  //超过5的元素,将找到的字符串转为大写并排序,

                        orderby name          //将LINQ执行的结果赋给匿名变量items;

                        select name.ToUpper();

            foreach (var item in items)

                Console.WriteLine(item);  //输出结果

            Console.Read();

 

        }

2.1.2查询数组应用

namespace MethodQuery

{

    class Program

    {

        IEnumerable<string> QueryMethod(ref int[] ints) //定义方法QueryMethod,返回查询

        {

            var intsToStrings = from i in ints where i > 4 select i.ToString();//查询ints中大于4的元素

            return intsToStrings;

        }

 

        static void Main(string[] args)

        {

            Program app = new Program();//创建对象app,以调用查询方法QueryMethod

            int[] nums = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //定义查询数据源nums

            var myQuery = app.QueryMethod(ref nums);//调用查询的方法QueryMetho1

            

            foreach (string s in myQuery)//执行查询

            {

                Console.WriteLine(s);

            }

 

            //修改查询,从myQuery结果中3取条结果按降序排列

            myQuery = (from str in myQuery  orderby str descending  select str). Take(3);

 

            Console.WriteLine("执行修改后的查询:");

            foreach (string s in myQuery) //执行修改后的查询

            {

                Console.WriteLine(s);

            }            

            Console.ReadKey(); //暂停运行,按任意键继续

        }

    }

}

2.2 查询实体对象集合

2.2.1 简单查询

static void QueryByID(string[] ids)

        {

            var queryNames =from student in students  let i = student.ID.ToString()

       where ids.Contains(i)   select new { student.Name, student.ID };

            foreach (var name in queryNames)

            {

                Console.WriteLine("姓名:{0},学号: {1}", name.Name, name.ID);

            }

        }

2.2.2 分组查询

static void Main(string[] args)

        {

            // 创建LINQ查询数据源 students

            List<Student> students = GetStudents();

 

            // 创建LINQ查询

            IEnumerable<Student> sortedStudents =

                from student in students

                orderby student.Last ascending, student.First ascending //先按Lastname排序,再按First排序

                select student;

 

            // 执行查询.

            Console.WriteLine("排好序的姓和名是:");

            foreach (Student student in sortedStudents)

                Console.WriteLine(student.Last + " " + student.First);

 

            // 创建分组并排序.             

            var sortedGroups =

                from student in students

                orderby student.Last, student.First

                group student by student.Last[0] into newGroup//按照Lastname的第一个字母进行分组

                orderby newGroup.Key

                select newGroup;

 

            // 执行查询.

            Console.WriteLine(Environment.NewLine + "分组排序结果是:");

            foreach (var studentGroup in sortedGroups)

            {

                Console.WriteLine("分组的首字母是:"+studentGroup.Key);

                foreach (var student in studentGroup)

                {

                    Console.WriteLine("   {0}, {1}", student.Last, student.First);

                }

            }

            

            Console.WriteLine("Press any key to exit.");

            Console.ReadKey();

        }

2.2.3 分组连接查询

        static void Main(string[] args)

        {

            int[] intAry1 = { 5, 15, 25, 30, 40, 50, 60, 70, };//定义数据源1

            int[] intAry2 = { 10, 20, 30,30, 40, 50, 60 };//定义数据源2            

            //分组联接查询,查询数据源1中和数据源2中相等的元素,将查询结果按照

            //第一个数据集中的元素进行分组,并将数据分组并保存到valGrp中;

            var query2 = from val1 in intAry1

                         join val2 in intAry2 on val1 equals val2 into valGrp

                         select new { Val1 = val1, Val2 = valGrp };

            //执行查询,输出结果

            Console.WriteLine("分组联接查询的结果,var1是分组关键字,var2分组查询结果");

            foreach (var obj in query2)

            {

                Console.Write("Var1={0},", obj.Val1);

                foreach (var item in obj.Val2)

                {

                    Console.Write("  Var2={0}   ", item);

                }

                Console.WriteLine();

            }

 

            //左外部联接查询,查询数据源1中和数据源2中相等的元素,将查询结果按照

            //第一个数据集中的所有元素进行分组,并将数据分组并保存到valGrp中;

            var query1 = from val1 in intAry1

                         join val2 in intAry2 on val1 equals val2 into valGrp

                         from grp in valGrp.DefaultIfEmpty()

                         select new { Val1 = val1, Val2 = grp };

            Console.WriteLine("左外部联接查询的结果,var1是分组关键字,var2左外连接查询结果");

                           

                foreach (var item in query1)

                {

                    Console.WriteLine(item);

                }                          

                Console.WriteLine();

           

            Console.Read();

        }

2.2.4 连接查询

static void Main(string[] args)

        {

            int[] intAry1 = { 5, 15, 25, 30, 40, 50, 60, 70, };//定义数据源1

            int[] intAry2 = { 10, 20, 30, 40, 50, 60 };//定义数据源2

            //内部连接查询,查询数据源1中和数据源2中相等的元素;

            var query1 = from val1 in intAry1

                         join val2 in intAry2 on val1 equals val2

                         select new { Val1 = val1, Val2 = val2 };

            //执行查询,输出结果

            Console.WriteLine("内部连接查询的结果是:");

            foreach (var item in query1)

            {

                Console.WriteLine(item);

            }

            Console.Read();

        }

2.2.5 查询结果处理

static void Main(string[] args)

        {

            //定义数据源

            int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            //查询LINQ语句,查询numbers中的偶数,按降序排列

            var even = from m in numbers where (m % 2 == 0) orderby m descending select m;

           

            //执行查询

            Console.Write("数组numbers中的偶数元素是:");

            foreach (var item in even )

                Console.Write("   {0}",item);            

           

            //利用Count方法,实现统计numbers中的偶数个数

            var evenCount = (from m in numbers where (m % 2 == 0)  select m).Count();

            Console.WriteLine("。偶数个数是:{0}", evenCount);            

           

            //混合模式求最大值的

            int maxValue = (from m in numbers select m).Max();

            //混合模式求最小值

            int minValue = (from m in numbers select m).Min();

            Console.Write("数组numbers中的最大值是:{0}", maxValue);

            Console.Write(",最小值是:{0}", minValue); 

            

            //用混合模式求平均值

            var aver = (from m in numbers select m).Average();

            Console.Write(",平均值是{0}", aver.ToString());

            //混合模式求总和

            var sum = (from m in numbers select m).Sum();            

            Console.WriteLine(",和是{0}", sum.ToString());

            

            //分区类查询,取出数组跳过第一个元素后的两个数组元素            

            var zone1 = numbers.Skip(1).Take(2);

            Console.Write("分区类查询结果:");

            foreach (var item in zone1)

            {

                Console.Write("   {0}", item);

            }

           // var zone2 = numbers.SkipWhile((x, i) => i < 5); //在numbers中查询不小于5的元素,结果为{5,6,7,8,9}

            // var zone3 = numbers.TakeWhile((x, i) => i < 5); //在numbers中查询小于5的元素,结果为{0,1,2,3,4}

            Console.ReadKey();

        }

static void Main(string[] args)

        {

//定义数据源

            int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            //查询LINQ语句,查询numbers中的偶数,按降序排列

           // var even = from m in numbers where (m % 2 == 0) orderby m descending select m;

            var even=numbers .Where (p => p%2 == 0).OrderByDescending(p => p).Select(p => p);

 

            //执行查询

            Console.Write("数组numbers中的偶数元素是:");

            foreach (var item in even)

                Console.Write("   {0}", item);

            Console.WriteLine();

 

            //利用Count方法,实现统计numbers中的偶数个数          

            int evenCount =  numbers.Where(p => p%2 == 0).Count();

            Console.WriteLine("数组numbers中的偶数个数是:{0}", evenCount);

 

            //纯粹查询语法

            int maxValue = numbers.Select(p => p).Max();

            int minValue = numbers.Select(p => p).Min();

            

            Console.WriteLine("数组numbers中的最大值是:{0}", maxValue);

            Console.WriteLine("数组numbers中的最小值是:{0}", minValue);

 

            //纯粹查询模式求平均值

            var num1 = numbers.Select(p => p).Average();            

            Console.WriteLine("混合模式获取numbers中元素的平均值是={0}", num1.ToString());

           

            //纯粹查询模式求总和

            var num3 = numbers.Select(p => p).Sum();

            

            Console.WriteLine("混合模式获取的数组numbers中元素的和={0}", num3.ToString());

            //分区类查询,取出数组跳过第一个元素后的两个数组元素            

            var num5 = numbers.Skip(1).Take(2);

            Console.Write("分区类查询结果:");

            foreach (var item in num5)

            {

                Console.Write("   {0}", item);

            }

            Console.ReadKey();

        }

2.2.6 Linq To DataSet

DataTable products = sds.Tables[0];

      // LINQ查询

      var productQuery =

         from product in products.AsEnumerable()                

         //orderby product.Field<string>(1) ascending

         select product;

         //输出Product表前10行,第一列ProductID表示Produc主键,

         //第二列Name表示ProductNumber产品的名称第三列ProductNumber表示唯一的产品标识号。

         foreach (DataRow product in productQuery)

         {

            Console.WriteLine("{0}   {1}   {2}", product[0], product[1], product[2]);

        }

 

//var productQuery1 =products.AsEnumerable().OrderByDescending (p=>p.Field <string >(1)).Select( p=>p );// LINQ查询

        var productQuery1 = products.AsEnumerable().Select(p => p);// LINQ查询

2.2.7 扩展

//声明一个有6个元素的字符串数组names

    string[] names = { "Everett", "Albert", "George", "Harris", "David" };

    var items = from name in names  //声明一个匿名变量items,使用LINQ在数组names中找出长度

        where name.Length >= 6  //超过5的元素,将找到的字符串转为大写并排序,

        orderby name          //将LINQ执行的结果赋给匿名变量items;

        select name.ToUpper();

    //等价写法,效果和上面语句一样

    var items2 = names.Where(name => name.Length >= 6).OrderBy(name => name).

Select(name => name.ToUpper()); 

 

    class Program

    {

        static void Main(string[] args)

        {

        /// <summary>

        /// 传统查询方式

        /// </summary>

            int[] numbers = new int[] { 1,2,5,8,9,10,11,14,17,16,21 };//定义数组用于查找

 

            List<int> even = new List<int>(); //定义集合用于存储查找的结果

 

            foreach (int number in numbers)  //遍历数组查找所有的偶数,添加到集合even中

            {

                if (number % 2 == 0)

                {

                    even.Add(number);

                }

            }

            even.Sort();   //对查找的结果排序

            

        }

    }

 

// 创建LINQ查询

            IEnumerable<Student> sortedStudents = students.OrderBy(p => p.Last).ThenBy(p => p.First);

            // 执行查询.

            Console.WriteLine("排好序的姓和名是:");

            foreach (Student student in sortedStudents)

                Console.WriteLine(student.Last + " " + student.First);

            // 创建分组并排序.             

            var sortedGroups = (students.OrderBy(p => p.Last).ThenBy(p => p.First).GroupBy(p => p.Last[0])).OrderBy(p => p.Key);

            // 执行查询.

            Console.WriteLine(Environment.NewLine + "分组排序结果是:");

            foreach (var studentGroup in sortedGroups)

            {

                Console.WriteLine("分组的首字母是:"+studentGroup.Key);

                foreach (var student in studentGroup)

                {

                    Console.WriteLine("   {0}, {1}", student.Last, student.First);

                }

            }

2.3 LinqDataType

using System.Data.Linq .Mapping ;

using System.Data.SqlClient;

namespace LinqDataType

{

    class Program

    {

        static void Main(string[] args)

        {

            //1. 不转换源数据的查询

            //下面代码演示了不对数据执行转换的 LINQ to Objects 查询操作。

            //源包含一个字符串序列,查询输出也是一个字符串序列,不转换源数据的类型。

            List<string> names = new List<string>{"Anderson","Bliss","Pessi","Tony","Pato"};

            IEnumerable<string> nameQuery = from name in names

                                            where name[0] =='P'

                                            select name;

            foreach (string str in nameQuery)

                Console.WriteLine(str);

 

           //下面的操作用到Northwind数据库中的Customers表,利用Linq to Sql创建DataCustomers.dbml

            //对数据库操作,创建数据库上下文对象db

            DataCustomersDataContext db=new DataCustomersDataContext ();

            //2. 转换源数据的查询

            //下面的代码演示了对数据执行简单转换的 LINQ to SQL 查询操作。

            //查询将Customer 对象序列作为输入,并只选择结果中的 Name 属性。因为 Name 是一个字符串,所以LINQ查询将Customer 对象转换为一个字符串输出。

 

            Table<Customers> customers = db.GetTable<Customers>();    //得到customers表      

IQueryable<string> custNameQuery = from cust in