DataContext类型(数据上下文)是System.Data.Linq命名空间下的重要类型,用于把查询句法翻译成SQL语句,以及把数据从数据库返回给调用方和把实体的修改写入数据库。
 
       DataContext提供了以下一些使用的功能:

  •          以日志形式记录DataContext生成的SQL
  •          执行SQL(包括查询和更新语句)
  •          创建和删除数据库

 
DataContext是实体和数据库之间的桥梁,那么首先我们需要定义映射到数据表的实体。

定义实体类

 
  
  1. [Table(Name = "tb_Students")]  
  2.    public class Student  
  3.    {  
  4.        [Column(IsPrimaryKey = true)]  
  5.        public int stuId { getset; }  
  6.        [Column(Name = "stuName")]  
  7.        public string stuName { getset; }  
  8.        [Column]  
  9.        public int stuAge { getset; }  
  10.    } 

以TempDBS数据库为例,上述Student类被映射成一个表,对应数据库中的 tb_Students表。然后在类型中定义了三个属性,对应表中的三个字段。其中,stuId字段是主键,如果没有指定Column特性的Name属性,那么系统会把属性名作为数据表的字段名,也就是说实体类的属性名就需要和数据表中的字段名一致。

现在,创建一个WinForm窗体,然后在窗体上加入一个DataGridView控件,使用下面的代码进行绑定数据:

 
  
  1. DataContext dc = new DataContext("Data Source=.;Initial Catalog=TempDBS;User ID=sa;Password=liufenghua");  
  2.         public FormApp()  
  3.         {  
  4.             InitializeComponent();  
  5.  
  6.             Table<Student> stuAll = dc.GetTable<Student>();  
  7.             dataGridView1.DataSource = from stu in stuAll  
  8.                                        where stu.stuId == 1  
  9.                                        select new { id = stu.stuId,name=stu.stuName,age=stu.stuAge };  
  10.         }  

使用DataContext类型把实体类和数据库中的数据进行关联。你可以直接在DataContext的构造方法中定义连接字符串,也可以使用IDbConnection:

 
  
  1. IDbConnection conn = new SqlConnection("Data Source=.;Initial Catalog=TempDBS;User ID=sa;Password=liufenghua");  
  2.             DataContext dc = new DataContext(conn);  
  3.             Table<Student> stuAll = dc.GetTable<Student>();  
  4.             dataGridView1.DataSource = from stu in stuAll  
  5.                                        where stu.stuId == 1  
  6.                                        select new { id = stu.stuId,name=stu.stuName,age=stu.stuAge }; 

之后,通过GetTable获取表示底层数据表的Table类型,显然,数据库中的tb_Students表的实体是Student类型。随后的查询句法,即使你不懂SQL应该也能看明白。从tb_Students
表中找出stuId等于1的记录,并把stuid,stuName以及stuAge封装成新的匿名类型进行返回。

强类型DataContext

 
  
  1. public partial class NorthwindDataContext :DataContext  
  2.    {  
  3.        public Table<Student> Students;  
  4.        public NorthwindDataContext(IDbConnection connection) : base(connection) { }  
  5.        public NorthwindDataContext(string connection) : base(connection) { }  
  6.    }  

强类型数据上下文使代码更简洁:

 
  
  1. NorthwindDataContext dc = new NorthwindDataContext("Data Source=.;Initial Catalog=TempDBS;User ID=sa;Password=liufenghua");  
  2.             dataGridView1.DataSource = from stu in dc.Students  
  3.                                        where stu.stuId == 1  
  4.                                        select new { id = stu.stuId,name = stu.stuName,age = stu.stuAge };  

日志功能

 
  
  1. NorthwindDataContext dc = new NorthwindDataContext("Data Source=.;Initial Catalog=TempDBS;User ID=sa;Password=liufenghua");  
  2.             StreamWriter sw = new StreamWriter(Application.StartupPath+"\\log.txt",true); //追加日记数据  
  3.             dataGridView1.DataSource = from stu in dc.Students  
  4.                                        where stu.stuId == 1  
  5.                                        select new { id = stu.stuId,name = stu.stuName,age = stu.stuAge };  
  6.             sw.Close();  
  7.             sw.Dispose(); 

运行程序后在项目所在目录生成了log.txt,每次查询都会把诸如下面的日志追加到文本文件中:

SELECT [t0].[stuId] AS [id], [t0].[stuName] AS [name], [t0].[stuAge] AS [age]
FROM [tb_Students] AS [t0]
WHERE [t0].[stuId] = @p0
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [1]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1

探究查询

 
  
  1. NorthwindDataContext dc = new NorthwindDataContext("Data Source=.;Initial Catalog=TempDBS;User ID=sa;Password=liufenghua");  
  2.            var select = from stu in dc.Students  
  3.                         where stu.stuId == 1  
  4.                         select new { id = stu.stuId,name = stu.stuName,age = stu.stuAge };  
  5.  
  6.            IDbCommand cmd = dc.GetCommand(select);  
  7.            Console.Write(cmd.CommandText);  
  8.            foreach(DbParameter parm in cmd.Parameters)  
  9.            {  
  10.                Console.Write(string.Format("参数名:{0},参数值:{1}",parm.ParameterName,parm.Value));  
  11.            }  
  12.            Student stus = dc.Students.First();  
  13.            stus.stuName = "刘华";  
  14.            IList<object> queryText = dc.GetChangeSet().Updates;  
  15.            Console.Write(((Student)queryText[0]).stuName);  

在这里,我们通过DataContext的GetCommand方法获取了查询对应的DbCommand,并且输出了CommandText和所有的DbParameter。之后,我们又通过GetChangeSet方法获取了修改后的实体,并输出了修改内容。

执行查询

 
  
  1. NorthwindDataContext dc = new NorthwindDataContext("Data Source=.;Initial Catalog=TempDBS;User ID=sa;Password=liufenghua");  
  2.             string newName = "刘华";  
  3.             dc.ExecuteCommand("update tb_Students set stuName={0} where stuId=1",newName);  
  4.             IEnumerable<Student> student = dc.ExecuteQuery<Student>("select * from tb_Students where stuId=1");  
  5.             dataGridView1.DataSource = student; 

虽然Linq to sql能实现90%以上的TSQL功能。但是不可否认,对于复杂的查询,使用TSQL能获得更好的效率。因此,DataContext类型也提供了执行SQL语句的能力。