linq to sql 存储过程
2011-09-26 11:20
351 查看
在介绍Linq to sql存储过程之前,先来介绍一下普通存储过程,这样更有助于大家对Linq to sql存储过程的理解。
首先在查询分析器运行下面的代码来创建一个存储过程:
然后打开IDE的服务器资源管理器,之前我们从表中拖动表到dbml设计视图,这次我们从存储过程中找到刚才创建的存储过程,然后拖动到设计视图。在方法面板中可以看到已经创建了一个sp_singleresultset的方法。
然后打开Northwind.designer.cs,可以找到下面的代码:
我们可以发现,IDE为这个Linq to sql存储过程单独生成了返回结果集的实体定义,你可能会觉得很奇怪,IDE怎么知道这个存储过程将会返回哪些数据那?其实,在把存储过程拖拽入dbml设计视图的时候,IDE就执行了类似下面的命令:
这样就可以直接获取Linq to sql存储过程返回的元数据而无须执行存储过程。
其实我们存储过程返回的就是顾客表的数据,如果你觉得为存储过程单独设置结果集实体有些浪费的话可以在存储过程的属性窗口中调整返回类型从“自动生成的类型”到Customer,不过以后你只能通过删除方法面板中的存储过程,然后重新添加来还原到“自动生成的类型”。下面,我们可以写如下的Linq to object代码进行查询:
var 单结果集存储过程 =
在这里确实是Linq to object的,因为查询句法不会被整句翻译成SQL,而是从Linq to sql存储过程存储过程的返回对象中再去对对象进行查询。SQL代码如下:
Linq to sql存储过程之带参数的存储过程
创建如下存储过程:
使用同样的方法生成存储过程方法,然后使用下面的代码进行测试:
结果输出了“01”。说明ID为“”的顾客数为0,而ID为“ALFKI”的顾客数为1。Linq to sql存储过程存储过程的输出参数被封装成了ref参数,对于C#语法来说非常合情合理。SQL代码如下
Linq to sql存储过程之带返回值的存储过程
再来创建第三个存储过程:
生成方法后,可以通过下面的代码进行测试:
运行后程序输出“100101”
Linq to sql存储过程之多结果集的存储过程
再来创建一个多结果集的存储过程:
找到生成的存储过程方法:
由于现在的VS2008会把多结果集Linq to sql存储过程识别为单结果集存储过程(只认识第一个结果集),我们只能对Linq to sql存储过程方法多小动手术,修改为:
然后使用下面的代码测试:
使用Linq to sql存储过程新增数据
存储过程除了可以直接调用之外,还可以用于实体的增删改操作。还记得在《一步一步学Linq to sql(三):增删改》中创建的留言簿程序吗?下面我们就来改造这个程序,使用存储过程而不是系统生成的SQL实现实体增删改。首先,我们创建下面的Linq to sql存储过程。
然后,打开留言簿dbml,把Linq to sql存储过程从服务器资源管理器拖拽到设计视图上。右键点击tbGuestBook实体类,选择配置行为。如下图,为插入操作选择刚才创建的存储过程方法,并进行参数匹配:
由于我们的Linq to sql存储过程只接受2个参数,相应修改以下创建留言的按钮处理事件:
运行程序后可以发现,在提交修改的时候调用了下面的SQL:
使用Linq to sql存储过程删除数据
创建如下Linq to sql存储过程:
按照前面的步骤生成Linq to sql存储过程方法,并为删除操作执行这个存储过程方法。在选择参数的时候我们可以看到,ID分当前值和原始值,我们选择当前值即可无须改动任何逻辑代码,进行删除留言操作后可以跟踪到下面的SQL:
Linq to sql存储过程之使用存储过程更改数据
创建如下存储过程:
由于更新的时候并不会更新主键,所以我们可以为两个参数都指定当前值。回复留言后可以跟踪到下面的SQL:
假设有这样一种应用,我们需要修改留言簿中不合法的用户名:
有个网友起名叫“admin”,我们要把所有这个名字修改为“notadmin”。那么,可以如下图设置update操作:
然后运行下面的测试代码:
运行程序后能跟踪到下面的SQL:
Linq to sql存储过程就看到这里了,你应该能明白当前值和原始值的含义了吧。
原文:http://developer.51cto.com/art/200909/152479.htm
首先在查询分析器运行下面的代码来创建一个存储过程:
create proc sp_singleresultset as set nocount on select * from customers
然后打开IDE的服务器资源管理器,之前我们从表中拖动表到dbml设计视图,这次我们从存储过程中找到刚才创建的存储过程,然后拖动到设计视图。在方法面板中可以看到已经创建了一个sp_singleresultset的方法。
然后打开Northwind.designer.cs,可以找到下面的代码:
[Function(Name="dbo.sp_singleresultset")] public ISingleResult sp_singleresultset() { IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod()))); return ((ISingleResult)(result.ReturnValue)); }
我们可以发现,IDE为这个Linq to sql存储过程单独生成了返回结果集的实体定义,你可能会觉得很奇怪,IDE怎么知道这个存储过程将会返回哪些数据那?其实,在把存储过程拖拽入dbml设计视图的时候,IDE就执行了类似下面的命令:
SET FMTONLY ON; exec Northwind.dbo.sp_singleresultset SET FMTONLY OFF;
这样就可以直接获取Linq to sql存储过程返回的元数据而无须执行存储过程。
其实我们存储过程返回的就是顾客表的数据,如果你觉得为存储过程单独设置结果集实体有些浪费的话可以在存储过程的属性窗口中调整返回类型从“自动生成的类型”到Customer,不过以后你只能通过删除方法面板中的存储过程,然后重新添加来还原到“自动生成的类型”。下面,我们可以写如下的Linq to object代码进行查询:
var 单结果集存储过程 =
from c in ctx.sp_singleresultset() where c.CustomerID.StartsWith("A") select c;
在这里确实是Linq to object的,因为查询句法不会被整句翻译成SQL,而是从Linq to sql存储过程存储过程的返回对象中再去对对象进行查询。SQL代码如下:
EXEC @RETURN_VALUE = [dbo].[sp_singleresultset] -- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
Linq to sql存储过程之带参数的存储过程
创建如下存储过程:
create proc [dbo].[sp_withparameter] @customerid nchar(5), @rowcount int output as set nocount on set @rowcount = (select count(*) from customers where customerid = @customerid)
使用同样的方法生成存储过程方法,然后使用下面的代码进行测试:
int? rowcount = -1; ctx.sp_withparameter("", ref rowcount); Response.Write(rowcount); ctx.sp_withparameter("ALFKI", ref rowcount); Response.Write(rowcount);
结果输出了“01”。说明ID为“”的顾客数为0,而ID为“ALFKI”的顾客数为1。Linq to sql存储过程存储过程的输出参数被封装成了ref参数,对于C#语法来说非常合情合理。SQL代码如下
EXEC @RETURN_VALUE = [dbo].[sp_withparameter] @customerid = @p0, @rowcount = @p1 OUTPUT -- @p0: Input StringFixedLength (Size = 5; Prec = 0; Scale = 0) [] -- @p1: InputOutput Int32 (Size = 0; Prec = 0; Scale = 0) [-1] -- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
Linq to sql存储过程之带返回值的存储过程
再来创建第三个存储过程:
create proc [dbo].[sp_withreturnvalue] @customerid nchar(5) as set nocount on if exists (select 1 from customers where customerid = @customerid) return 101 else return 100
生成方法后,可以通过下面的代码进行测试:
Response.Write(ctx.sp_withreturnvalue("")); Response.Write(ctx.sp_withreturnvalue("ALFKI"));
运行后程序输出“100101”
Linq to sql存储过程之多结果集的存储过程
再来创建一个多结果集的存储过程:
create proc [dbo].[sp_multiresultset] as set nocount on select * from customers select * from employees
找到生成的存储过程方法:
[Function(Name="dbo.sp_multiresultset")] public ISingleResult sp_multiresultset() { IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod()))); return ((ISingleResult)(result.ReturnValue)); }
由于现在的VS2008会把多结果集Linq to sql存储过程识别为单结果集存储过程(只认识第一个结果集),我们只能对Linq to sql存储过程方法多小动手术,修改为:
[Function(Name="dbo.sp_multiresultset")] [ResultType(typeof(Customer))] [ResultType(typeof(Employee))] public IMultipleResults sp_multiresultset() { IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod()))); return (IMultipleResults)(result.ReturnValue); }
然后使用下面的代码测试:
var 多结果集存储过程 = ctx.sp_multiresultset(); var Customers = 多结果集存储过程.GetResult(); var Employees = 多结果集存储过程.GetResult(); GridView1.DataSource = from emp in Employees where emp.FirstName.Contains("A") select emp; GridView1.DataBind(); GridView2.DataSource = from c in Customers where c.CustomerID.StartsWith("A") select c; GridView2.DataBind();
使用Linq to sql存储过程新增数据
存储过程除了可以直接调用之外,还可以用于实体的增删改操作。还记得在《一步一步学Linq to sql(三):增删改》中创建的留言簿程序吗?下面我们就来改造这个程序,使用存储过程而不是系统生成的SQL实现实体增删改。首先,我们创建下面的Linq to sql存储过程。
create proc sendmessage @username varchar(50), @message varchar(500) as insert into tbguestbook (id,username,posttime,[message],isreplied,reply) values (newid(),@username,getdate(),@message,0,'')
然后,打开留言簿dbml,把Linq to sql存储过程从服务器资源管理器拖拽到设计视图上。右键点击tbGuestBook实体类,选择配置行为。如下图,为插入操作选择刚才创建的存储过程方法,并进行参数匹配:
由于我们的Linq to sql存储过程只接受2个参数,相应修改以下创建留言的按钮处理事件:
protected void btn_SendMessage_Click(object sender, EventArgs e) { tbGuestBook gb = new tbGuestBook(); gb.UserName = tb_UserName.Text; gb.Message = tb_Message.Text; ctx.tbGuestBooks.Add(gb); ctx.SubmitChanges(); SetBind(); }
运行程序后可以发现,在提交修改的时候调用了下面的SQL:
EXEC @RETURN_VALUE = [dbo].[sendmessage] @username = @p0, @message = @p1 -- @p0: Input AnsiString (Size = 5; Prec = 0; Scale = 0) [zhuye] -- @p1: Input AnsiString (Size = 11; Prec = 0; Scale = 0) [new message] -- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
使用Linq to sql存储过程删除数据
创建如下Linq to sql存储过程:
create proc delmessage @id uniqueidentifier as delete tbguestbook where id=@id
按照前面的步骤生成Linq to sql存储过程方法,并为删除操作执行这个存储过程方法。在选择参数的时候我们可以看到,ID分当前值和原始值,我们选择当前值即可无须改动任何逻辑代码,进行删除留言操作后可以跟踪到下面的SQL:
EXEC @RETURN_VALUE = [dbo].[delmessage] @id = @p0 -- @p0: Input Guid (Size = 0; Prec = 0; Scale = 0) [9e3c5ee3-2575-458e-899d-4b0bf73e0849] -- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
Linq to sql存储过程之使用存储过程更改数据
创建如下存储过程:
create proc replymessage @id uniqueidentifier, @reply varchar(500) as update tbguestbook set reply=@reply,isreplied=1 where id=@id
由于更新的时候并不会更新主键,所以我们可以为两个参数都指定当前值。回复留言后可以跟踪到下面的SQL:
EXEC @RETURN_VALUE = [dbo].[replymessage] @id = @p0, @reply = @p1 -- @p0: Input Guid (Size = 0; Prec = 0; Scale = 0) [67a69d0f-a88b-4b22-8939-fed021eb1cb5] -- @p1: Input AnsiString (Size = 6; Prec = 0; Scale = 0) [464456] -- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
假设有这样一种应用,我们需要修改留言簿中不合法的用户名:
create proc modiusername @oldusername varchar(50), @newusername varchar(50) as update tbguestbook set username=@newusername where username = @oldusername
有个网友起名叫“admin”,我们要把所有这个名字修改为“notadmin”。那么,可以如下图设置update操作:
然后运行下面的测试代码:
var messages = from gb in ctx.tbGuestBooks select gb; foreach (var gb in messages) { if(gb.UserName == "admin") gb.UserName = "notadmin"; }
运行程序后能跟踪到下面的SQL:
SELECT [t0].[ID], [t0].[UserName], [t0].[PostTime], [t0].[Message], [t0].[IsReplied], [t0].[Reply] FROM [dbo].[tbGuestBook] AS [t0] EXEC @RETURN_VALUE = [dbo].[modiusername] @oldusername = @p0, @newusername = @p1 -- @p0: Input AnsiString (Size = 5; Prec = 0; Scale = 0) [admin] -- @p1: Input AnsiString (Size = 8; Prec = 0; Scale = 0) [notadmin] -- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
Linq to sql存储过程就看到这里了,你应该能明白当前值和原始值的含义了吧。
原文:http://developer.51cto.com/art/200909/152479.htm
相关文章推荐
- 步步为营VS 2008 + .NET 3.5(10) - DLINQ(LINQ to SQL)之调用存储过程的添加、查询、更新和删除
- Linq to sql:带参数的存储过程
- sql to linq 之存储过程偏
- Linq to sql(五):存储过程(六)
- Linq to sql:带返回值的存储过程
- LINQ体验(14)——LINQ to SQL语句之存储过程
- 一步一步学Linq to sql(五):存储过程
- 代替Linq to SQL----存储过程
- DLINQ(LINQ to SQL)之调用存储过程的添加、查询、更新和删除
- 一步一步学Linq to sql(五):存储过程
- LINQ to SQL语句之存储过程
- 步步为营VS 2008 + .NET 3.5(10) - DLINQ(LINQ to SQL)之调用存储过程的添加、查询、更新和删除
- LINQ体验(14)——LINQ to SQL语句之存储过程
- 【数据库】存储过程在LINQ TO SQL中的应用
- Linq to sql(五):存储过程(二)
- LINQ体验(14)——LINQ to SQL语句之存储过程
- 步步为营VS 2008 + .NET 3.5(10) - DLINQ(LINQ to SQL)之调用存储过程的添加、查询、更新和删除
- 步步为营VS 2008 + .NET 3.5(10) - DLINQ(LINQ to SQL)之调用存储过程的添加、查询、更新和删除
- [代码]如何使用为多个结果形状映射的存储过程(LINQ to SQL)
- 一步一步学Linq to sql(五):存储过程