使用LINQ查询关系型数据库

一、概述
LINQ支持自定义提供者,这些提供者将LINQ表达式树转换为数据源所支持的语言,值得关注的是LINQ可以通过IQueryable接口访问ADO.NET对象。
LINQ可以直接对DataSet进行查询,也可以用DataContext和Table(实现了ITable、IQueryable、IEnumerable)。
最基本的工作是定义一个对象关系映射(ORM),用于将C#实体类与数据库中的表映射起来。
为了使用LINQ to SQL,需要一下东西:
1. 引用:System.Data.Linq
2. 一个DataContext实例,用来连接字符串
3. 一个与数据库对应的实体类

二、定义表对象
当我们为数据库中的表实现一个自定义类(实体类)的时候,就是在定义一个ORM。

【示例:查询所有记录或单条记录或删除指定记录】
using System;
using System.Linq;
using System.Data.Linq;

namespace 简单的ORM和LINQToSQL示例
{
    class Program
    {
        //定义一个私有的连接字符串
        private static readonly string connectionString = "Data Source=.;Initial Catalog=db_Customer;Integrated Security=SSPI;";

        static void Main(string[] args)
        {
            //表示Linq to SQL框架的主入口点,DataContext实例,通过一个连接字符串连接你的数据库
            DataContext customerContext = new DataContext(connectionString);
            //Table:表示基础数据库中特定类型的表。
            //GetTable:返回特定类型的对象的集合,其中类型由 TEntity 参数定义
            Table customers = customerContext.GetTable();

            var seperator = new string('*', 40);
            Console.WriteLine(seperator);
            //查询所有数据
            var startsWith = from c in customers
                             select c;
            Array.ForEach(startsWith.ToArray(), c => Console.WriteLine(c));
            //Log:获取或设置为目标编写SQL查询或命令
            //Out:获取标准输出流
            //customerContext.Log = Console.Out;
            Console.WriteLine(seperator);
            //查询单条数据(按条件查询)
            var singleInfo = from c in customers
                             where c.CustomerID[c.CustomerID.Length - 1] == '3'
                             select c;
            Array.ForEach(singleInfo.ToArray(), c => Console.WriteLine(c));
            Console.WriteLine(seperator);
            //删除指定的一条数据,根据字段CustomerID='1009'
            var deleteInfo = customers.SingleOrDefault(s => s.CustomerID == "1009");
            //Console.WriteLine(deleteInfo);
            if (deleteInfo == null)
            {
                throw new Exception ("没有该条数据");
            }
            customers.DeleteOnSubmit(deleteInfo);
            customerContext.SubmitChanges();
            Console.ReadKey();
        }
    }
}
【增加、编辑一条记录】
using System;
using System.Linq;
using System.Data.Linq;
using 简单的ORM和LINQToSQL示例;
using System.Collections.Generic;

namespace 增加修改记录
{
    class Program
    {
        private static readonly string connectionString = "Data Source=.;Initial Catalog=db_Customer;Integrated Security=SSPI;";
        static void Main(string[] args)
        {
            DataContext context = new DataContext(connectionString);
            Table customers = context.GetTable();
            var seperator = new string('*', 40);
            //插入一条记录
            Customer c = new Customer
            {
                CustomerID = "201",
                ContactName = "徐帅",
                Phone = "12122121121",
                CompanyName="妈蛋的哈哈哈"
            };
            customers.InsertOnSubmit(c);
            //插入多条数据
            var cc = new List
            {
                new Customer {CustomerID="202",ContactName="大胖", Phone="32323232323",CompanyName="公司名" },
                new Customer {CustomerID="003",ContactName="fsfds", Phone="656765768",CompanyName="公司的名字" },
                new Customer {CustomerID="004",ContactName="艰苦艰苦", Phone="0897876565",CompanyName="公司的haoming" }
            };
            customers.InsertAllOnSubmit(cc);
            //修改一条记录
            var editInfo = customers.SingleOrDefault(s => s.CustomerID =="1001");
            editInfo.ContactName = "修改秀嘎";
            context.SubmitChanges();
            Console.ReadKey();
        }
    }
}
映射到数据库表的类叫实体类。对LINQ而言,实体都要用TableAttribute和ColumnAttribute进行修饰。
 ColumnAttribute可以应用在任何字段或属性上(public、private、internal),不过当LINQ把修改保存回数据库时,实体中只有那些带有ColumnAttribute的元素才会被持久化。
ColumnAttribute的命名参数
命名属性描述备注AutoSync指示何时将该列与数据库进行同步比如:AutoSync.OnInsertCanBeNull指示该列是否可以包含null值 DbType表示DbType枚举值之一 Expression说明计算列是如何产生的 IsDbGenerated指示该列是否是自动生成的比如自动生成的主键列(数据库中用IDENTITY)IsDiscriminator指示该列是否包含LINQ TO SQL继承层次结构的鉴别器值 IsPrimaryKey指示该列是否是主键 IsVersion指示该列是否是数据库时间戳或版本号 Name显示列名称 Storage标识当前实体类中用于存储该列的值的字段 UpdateCheck指示如何检测并发冲突 
【示例】
[Column(IsPrimaryKey =true,Name = "CustomerID",Storage ="customerid",CanBeNull =false,DbType ="varchar(20)")]
        public string CustomerID { get; set; }

三、查看由LINQ生成的查询文本

【示例】
/表示Linq to SQL框架的主入口点,DataContext实例,通过一个连接字符串连接你的数据库
            DataContext customerContext = new DataContext(connectionString);
            //Table:表示基础数据库中特定类型的表。
            //GetTable:返回特定类型的对象的集合,其中类型由 TEntity 参数定义
            Table customers = customerContext.GetTable();

            Console.WriteLine("SELECT:{0}", customerContext.GetCommand(customers).CommandText);
【结果】
SELECT:SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [tb_Customer] AS [t0]
以上我们都是直接使用DataContext类的,当然我们也可以直接继承DataContext,并在新类中嵌入诸如连接字符串之类的一些信息,这会让LINQ to SQL变得更加容易使用。
DataContext是LINQ to SQL的起点。一个DataContext实例代表的是针对一组相关操作的一个“工作单元”。DataContext是一个轻量级的类,常常用于方法范围级别,而不是创建一个DataContext实例并重复使用。
以下,我定义了一个newDataContext类,用于继承DataContext类,并嵌入了连接字符串。
【示例】
using System;
using System.Linq;
using 查看由LINQ生成的查询文本;
using System.Data.Linq;

namespace 通过DataContext对象联接关系型数据
{
    class Program
    {
        static void Main(string[] args)
        {
            newDataContext context = new newDataContext();
            Table details = context.GetTable();
            //查看SQL文本
            Console.WriteLine("Select:{0}", context.GetCommand(details).CommandText);
            Console.WriteLine();

            var result = from detail in details
                         where detail.OrderID == "1005"
                         select detail;
            Array.ForEach(result.ToArray(), r => Console.WriteLine(r));
            Console.ReadKey();
        }
    }
    public class newDataContext : DataContext
    {
        private static readonly string connectionString = "Data Source=.;Initial Catalog=db_Customer;Integrated Security=true";
        public newDataContext() : base(connectionString)
        {
        }
    }
}
四、查询数据集 
       LINQ to DataSet的目的并不是取代ADO.NET,实际上,LINQ to DataSet代码是建立在ADO.NET代码之上的,并且与之协同工作。学过ADO.NET的都知道,当数据提供程序不同时,所采取的类也有些许差异(尽管步骤是一样的,思想是一样的),值得注意的是,当数据来自多个数据提供者(或执行本地查询,或生成报表和分析)时,LINQ to DataSet将更有用。
那么,LINQ对DataSet的支持主要是通过哪两个类呢?
linq对DataSet的支持
类名 扩展方法      备注
DataRowExtensions Field   SetField 行扩展方法提供对数据的字段级访问
DataTableExtensions AsDataView  AsEnumerable  CopyToDataTable 表扩展方法将会产生一个可查询的序列
【示例】
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Data.SqlClient;

namespace 从DataTable中获取数据
{
    class Program
    {
        private static readonly string connectionString = "Data Source=.;Initial Catalog=db_Customer;Integrated Security=true";

        static void Main(string[] args)
        {
            //创建一个存储数据的容器“内存”
            DataSet data = new DataSet();
            using(SqlConnection con=new SqlConnection(connectionString))
            {
                con.Open();
                string selectSQL = "select * from tb_OrderDetail";
                SqlCommand com = new SqlCommand(selectSQL, con);
                //查询数据
                SqlDataAdapter adapter = new SqlDataAdapter(com);
                //将查询到的数据以表的形式放到data中
                adapter.Fill(data, "OrderDetails");
            }
            //定义一个数据表并找到容器中的表
            DataTable orderDetailTable = data.Tables["OrderDetails"];
            //对该表进行查询、筛选、排序 ,使用了ADO.NET和一个LINQ to DataSet查询
            //而这个查询则使用了AsEnumerable扩展方法
            IEnumerable orderDetails = from orderDetail in orderDetailTable.AsEnumerable()
                                                where orderDetail.Field("discount")> 0.8
                                                orderby orderDetail.Field("discount")
                                                select orderDetail;

            Console.WriteLine("OrderDetai Information :");
            foreach (DataRow row in orderDetails.Take(3))
            {
                Console.WriteLine("订单号:"+row.Field("orderid"));
                Console.WriteLine("产品编号:"+row.Field("productid"));
                Console.WriteLine("价格:"+row.Field("unitprice"));
                Console.WriteLine("销售总数:"+row.Field("quantity"));
                Console.WriteLine("折扣率:"+row.Field("discount")==null?0: row.Field("discount"));
                Console.WriteLine(Environment.NewLine);
            }
            Console.ReadKey();
        }
    }
}
使用LINQ查询关系型数据库_第1张图片
五、在DataSet上定义联接
using System;
using System.Linq;
using System.Data;
using System.Data.SqlClient;

namespace 在DataSet上定义联接
{
    class Program
    {
        private static readonly string connectionString = "Data Source=.;Initial Catalog=db_Customer;Integrated Security=true";

        static void Main(string[] args)
        {
            //一次性调用多个SQL语句
            const string selectSQL = "select * from tb_OrderDetail;select * from tb_Order;";

            DataSet data = new DataSet();
            using(SqlConnection con=new SqlConnection(connectionString))
            {
                con.Open();
                SqlCommand com = new SqlCommand(selectSQL, con);
                com.CommandType = CommandType.Text;
                SqlDataAdapter adapter = new SqlDataAdapter(com);
                adapter.Fill(data);
            }

            DataTable orders = data.Tables[0];
            DataTable orderDetails = data.Tables[1];

            var orderResults = from order in orders.AsEnumerable()
                               join detail in orderDetails.AsEnumerable()
                               on order.Field("orderid") equals detail.Field("orderid")
                               orderby order.Field("discount")
                               select new
                               {
                                   OrderID = detail.Field("orderid"),
                                   ProductID = detail.Field("productid"),
                                   UnitPrice = order.Field("unitprice"),
                                   Quantity = order.Field("quantity"),
                                   Discount = order.Field("discount")
                               };

            Console.WriteLine("Orders & Details");
            foreach (var item in orderResults)
            {
                Console.WriteLine("Order ID:{0}", item.OrderID);
                Console.WriteLine("Product ID:{0}", item.ProductID);
                Console.WriteLine("Unitprice:{0}", item.UnitPrice);
                Console.WriteLine("Quantity:{0}", item.Quantity);
                Console.WriteLine("Discount:{0}", item.Discount);
                Console.WriteLine();
            }
            Console.ReadKey();
        }
    }
}

六、使用LINQ to DataSet进行数据绑定
    数据绑定的关键是IEnumerable,数据绑定是先通过IEnumerable和反射来读取公共属性的名称,然后将这些属性及其值绑定到控件,如GridView。
     可绑定性也可以通过实现了IBindgList的类来提供。IBindgList本身就实现了IEnumerable接口。由于Linq序列返回的是IEnumerable对象,因此它们本身是可绑定的。EntitySet是可用于实体的属性,它本身就表示着一种映射关系。EntitySet也实现了IEnumerable,因此它也是可绑定的。

     实现方式很简单,即通过linq语句查询数据库,得到的结果为数据源,然后进行绑定

你可能感兴趣的:(LINQ)