【IT168 技术资讯】
1. 概述
通过LINQ to SQL基础篇我们对LINQ to SQL有了一个概要的认识,本文我们来认识在LINQ to SQL中处于非常重要地位的一个对象——DataContext(数据上下文),它位于System.Data.Linq命名空间下,是实体和数据库之间的一个桥梁。

DataContext主要提供了如下几个功能:
A. 记录生成的SQL语句,这对于我们调试LINQ to SQL时是非常有用的,可以通过查看记录的SQL语句,来分析LINQ to SQL在数据库中执行了什么。
B. 执行SQL语句。LINQ to SQL通过查询句法和Lambda表达式提供了强大的功能,能完成T-SQL 90%以上的功能,如果在开发中,遇到非常复杂的查询,无法用查询句法或者Lambda表达式来实现,你可以使用自己熟悉的T-SQL来完成。
C. 创建、删除数据库。在第一篇中我就说过,LINQ to SQL是一个轻量级的O/R Mapping,使用LINQ to SQL可以不用考虑数据库表之间的关系,直接考虑你的业务对象关系,设计好实体类之后,通过DataContext可以自动创建数据库。
2. 创建DataContext
在DataContext中,提供了如下四种重载方式的构造函数,就是说我们可以通过四种方式来创建一个DataContext对象:
Code1:
public DataContext(IDbConnection connection);
public DataContext(string fileOrServerOrConnection);
public DataContext(IDbConnection connection, MappingSource mapping);
public DataContext(string fileOrServerOrConnection, MappingSource mapping);
我们经常使用的有两种:一是使用连接字符串,作为DataContext构造函数的参数:
Code2
public DataContext CreateDataContext()这里为了避免硬编码连接字符串,你也可以把连接字符串放在配置文件中。创建DataContext对象的第二种方式就是使用 IDbConnection对象作为DataContext构造函数的参数:
{
DataContext db = new DataContext(@"Server=Esint-lhj\Sql2005;User Id=sa;Password=sql2005;Database=MSPetShop4");
return db;
}
Code3:
public DataContext CreateDataContext()3. 创建强类型的DataContext
{
IDbConnection conn = new SqlConnection(@"Server=Esint-lhj\Sql2005;User Id=sa;Password=sql2005;Database=MSPetShop4");
DataContext db = new DataContext(conn);
return db;
}
虽然可以使用上面的两种方法来创建一个DataContext,但是在实际使用中,用的最多的还是创建强类型的DataContext,使用强类型的DataContext的好处是可以获取IDE的智能提示、使后面的使用代码更加优雅。如下示例代码创建一个强类型的DataContext:
Code4:
[Database(Name="Blog")]在Code4中创建了一个强类型BlogDataContext的同时,也在其中定义了一个Posts的属性,用来获取Blog数据库中所有Post的集合。这样,可以如下进行BlogDataContext的使用:
public class BlogDataContext : DataContext
{
public BlogDataContext()
: base(@"Server=Esint-lhj\Sql2005;User Id=sa;Password=sql2005;Database=Blog")
{
}
public Table<Post> Posts
{
get
{
return this.GetTable<Post>();
}
}
}
Code5:
public class Program并且获得很好的智能提示的支持,如下图所示:
{
static void Main(string[] args)
{
BlogDataContext db = new BlogDataContext();
IEnumerable<Post> posts = from p in db.Posts
orderby p.PubDate
select p;
}
}

4. 记录生成SQL语句
上一篇(创建你的第一个LINQ to SQL应用程序)文章结尾,我曾经提出过一个问题,就是如何知道查询句法在执行后相当于执行了什么样的T-SQL?本篇文章的这一节,你将得到答案。在DataContext中,提供了记录生成SQL的功能,通过DataContext提供了一个属性Log,可以指定一个TextWriter对象给DataContext,它将会以日志的形式记录执行过程中所产生的SQL语句。
Code6:
public TextWriter Log { get; set; }
如果我们执行如下代码片段: Code7:
static void Main(string[] args)执行完成后会在C盘的根目下会创建一个Log.txt的文件,打开文件可以看到生成了如下的SQL语句:
{
BlogDataContext db = new BlogDataContext();
using (StreamWriter sw = new StreamWriter(@"c:\log.txt", true))
{
db.Log = sw;
IEnumerable<Post> posts = from p in db.Posts
orderby p.PubDate
select p;
foreach (var post in posts)
{
Console.WriteLine(post.Title);
}
Console.ReadLine();
}
}
Code8:
SELECT [t0].[Id], [t0].[Title], [t0].[Author], [t0].[PubDate], [t0].[Description]这个功能虽然使用起来非常的简单,只要指定Log属性就可以了,但是它却非常的有用,尤其在调试程序的程序,我们可以清楚的知道在数据库中执行了什么样的操作。
FROM [Posts] AS [t0]
ORDER BY [t0].[PubDate]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8
5. 执行SQL语句
LINQ查询句法提供了非常强大的功能,基本能满足我们90%以上的要求,但是如果在实际开发中,遇到了非常复杂的查询需求或者使用LINQ查询句法无法完成的操作,LINQ to SQL也支持我们直接使用T-SQL来完成。在DataContext中,提供了如下这样三个方法,用来执行SQL语句:
Code9:
public int ExecuteCommand(string command, params object[] parameters);看下面这段代码:
public IEnumerable<TResult> ExecuteQuery<TResult>(string query, params object[] parameters);
public IEnumerable ExecuteQuery(Type elementType, string query, params object[] parameters);
Code10:
static void Main(string[] args)在这里,并没有使用查询句法,而是使用T-SQL语句进行查询,并调用ExecuteQuery方法执行SQL语句,它执行的结果跟上面Code7中的代码执行的结果是一样的,这在一定程序上给我们使用LINQ to SQL带来极大的灵活性。
{
BlogDataContext db = new BlogDataContext();
using (StreamWriter sw = new StreamWriter(@"c:\log.txt", true))
{
db.Log = sw;
String sql = "SELECT * FROM Posts ORDER BY PubDate";
IEnumerable<Post> posts = db.ExecuteQuery<Post>(sql);
foreach (var post in posts)
{
Console.WriteLine(post.Title);
}
Console.ReadLine();
}
}
6. Create、Drop数据库
DataContext提供了创建、删除数据库的功能,允许我们首先设计自己的业务实体,然后通过业务实体生成数据库表。可以通过CreateDatabase()或DeleteDatabase()来生成、删除数据库。在创建和删除之前,我们可以通过DatabaseExists方法来判断服务器上是否存在相应的数据库。如有这样一段代码:
Code11:
[Database(Name="Blog")]相当于在数据库执行了如下的SQL语句:
public class BlogDataContext : DataContext
{
public BlogDataContext()
: base(@"Server=Esint-lhj\Sql2005;User Id=sa;Password=sql2005;Database=Blog")
{
}
public Table<Post> Posts
{
get
{
return this.GetTable<Post>();
}
}
}
[Table(Name = "Posts")]
public class Post
{
[Column(IsPrimaryKey = true, IsDbGenerated = true)]
public int Id { get; set; }
[Column]
public string Title { get; set; }
[Column]
public string Author { get; set; }
[Column]
public DateTime PubDate { get; set; }
[Column]
public string Description { get; set; }
}
Code12:
CREATE DATABASE [Blog]7. 结束语
CREATE DATABASE [Blog]
.Net SqlClient Data Provider: 已将数据库上下文更改为 'Blog'。.
SET ARITHABORT ON
CREATE TABLE [Posts](
[Id] Int NOT NULL IDENTITY,
[Title] NVarChar(4000),
[Author] NVarChar(4000),
[PubDate] DateTime NOT NULL,
[Description] NVarChar(4000),
CONSTRAINT [PK_Posts] PRIMARY KEY ([Id])
)
关于数据上下文DataContext对象,就写到这里了,用一句话来总DataContext:它是实体和数据库之间的桥梁。在下篇文章中,我讲就查询句法进行详细的说明。