系列文章导航:
走进Linq--Linq横空出世篇
走进Linq-辉煌的背后
走进Linq-Linq大观园
不能不说的C#特性-对象集合初始化器
不能不说的C#特性-匿名类型与隐式类型局部变量
不能不说的C#特性-扩展方法
不能不说的C#特性-匿名方法和Lambda表达式
不能不说的C#特性-迭代器(上)及一些研究过程中的副产品
不能不说的C#特性-迭代器(下),yield以及流的延迟计算
走进Linq-Linq to Objects(上)基础篇
走进Linq-Linq to Objects(下)实例篇
走进Linq-Linq to SQL感性认识篇
走进Linq-Linq to SQL How do I(1)
走进Linq-Linq to SQL How do I(2)
走进Linq-Linq to SQL How do I(3)
走进Linq-How do I(4)拾遗补零篇第一节
走进Linq-Linq to SQL源代码赏析 Table的获取过程
走进Linq-Linq to SQL源代码赏析之Provider的初始化
走进Linq-Linq to SQL源代码赏析,通过Linq to SQL看Linq
最近很忙,真的很忙,所以这个系列好久没更新了,从今天起我又开始了我的走进Linq之旅。Linq to SQL的用法基本上都说完了,还有一些细枝末节的地方需要聊聊。
强类型DataContext
在Linq to SQL的第一篇的时候就说道DataContext是一个入口点,我们使用Linq to SQL做的一些操作几乎都是施加在这个类上的。在使用VS的设计器生成的代码里,我们会看到一个从DataContext继承的局部类,大家都习惯的将这个类称之为强类型的DataContext,她对DataContext做了进一步的封装。
今天我们先就对DataContext一些没有介绍过的地方详细讨论一下。
首先我们先手写一个强类型的DataContext:
强类型的DataContext
[Database(Name="CnBlogs")]
public class CnBlogsDataContext : DataContext
{
public CnBlogsDataContext(string fileOrConnectionString)
: base(fileOrConnectionString)
{ }
public CnBlogsDataContext(string fileOrConnectionString, MappingSource mapping)
: base(fileOrConnectionString, mapping)
{ }
public CnBlogsDataContext(IDbConnection conn)
: base(conn)
{ }
public CnBlogsDataContext(IDbConnection conn, MappingSource mapping)
: base(conn, mapping)
{ }
public Table<Post> Posts
{
get { return this.GetTable<Post>(); }
}
public Table<Blog> Blogs
{
get { return this.GetTable<Blog>(); }
}
public Table<User> Users
{
get { return this.GetTable<User>(); }
}
[Function(Name = "dbo.GetPostsByBlogId")]
public ISingleResult<Post> GetPostsByBlogId(
[Parameter(Name="blogid",DbType="int")]
int blogid)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), blogid);
return (ISingleResult<Post>)result.ReturnValue;
}
[Function(Name = "dbo.GetBblogsOrPosts")]
[ResultType(typeof(Blog))]
[ResultType(typeof(Post))]
public IMultipleResults GetBlogsOrPosts(
[Parameter(Name = "kind", DbType = "int")]
int kind)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)MethodInfo.GetCurrentMethod()), kind);
return (IMultipleResults)result.ReturnValue;
}
[Function(Name = "dbo.GetBblogsAndPosts")]
[ResultType(typeof(Blog))]
[ResultType(typeof(Post))]
public IMultipleResults GetBlogsOrPosts()
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)MethodInfo.GetCurrentMethod()));
return (IMultipleResults)result.ReturnValue;
}
}
在这个类里出现了四个前面没有看到的特性:Database,Function,Parameter,ResultType至于Database就不用说了,就是做数据库映射的。下面对其它三个做一些讨论:
Function、Parameter和ResultType
Linq to SQL不仅仅能做字段与属性之间的映射,还可以将存储过程或用户自定义方法与.net里的方法之间做映射,功能是不是很强大?这个映射就是通过Function和Parameter共同完成的。
Function有两个属性IsComposable和Name,Name就是用来指定数据库中存储过程或者用户自定义方法的名字,当IsComposable为true的时候,则表明该方法对应着一个用户自定义方法,否则对应一个存储过程,默认是false。Function特性只能放在方法上面。
Parameter就是用来映射存储过程或方法接受的参数。
还是用例子来说明:
假设有这样的一个存储过程,通过blogid找出其所有的随笔
ALTER PROCEDURE dbo.GetPostsByBlogId
(
@blogid int
)
AS
SELECT postid,blogid,title,body,createdate FROM posts WHERE blogid = @blogid
RETURN
我要在.net里写一个方法来对应这个存储过程
[Function(Name = "dbo.GetPostsByBlogId")]
public ISingleResult<Post> GetPostsByBlogId(
[Parameter(Name="blogid",DbType="int")]
int blogid)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), blogid);
return (ISingleResult<Post>)result.ReturnValue;
}
现在你可以以调用.net方法的形式直接调用这个方法来调用存储过程
Code
ISingleResult<Post> posts = dbCtx.GetPostsByBlogId(1);
foreach (var p in posts)
{
Console.WriteLine(p.Title);
}
这样就将存储过程封装成.NET的方法了,调用看看:
使用存储过程的时候,我们往往使用一个条件参数,根据条件参数的不同返回不同的结果集:
ALTER PROCEDURE dbo.GetBblogsOrPosts
(
@kind int,
)
AS
if @kind = 1
SELECT * FROM blogs
ELSE
SELECT * FROM posts
RETURN
在.NET里使用这样的方法映射:
[Function(Name = "dbo.GetBblogsOrPosts")]
[ResultType(typeof(Blog))]
[ResultType(typeof(Post))]
public IMultipleResults GetBlogsOrPosts(
[Parameter(Name = "kind", DbType = "int")]
int kind)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)MethodInfo.GetCurrentMethod()), kind);
return (IMultipleResults)result.ReturnValue;
}
返回一个ImultipleResults对象,该对象有一个GetResult方法:
IMultipleResults results = dbCtx.GetBlogsOrPosts(1);
foreach (var b in results.GetResult<Blog>())
{
Console.WriteLine(b.Name;
}
除了支持这种存储过程外,还支持这样的:
CREATE PROCEDURE dbo.GetBblogsAndPosts
AS
SELECT * FROM blogs
SELECT * FROM posts
RETURN
使用方法还是和上面的一样。