然后打开IDE的服务器资源管理器,之前我们从表中拖动表到dbml设计视图,这次我们从存储过程中找到刚才创建的存储过程,然后拖动到设计视图。在方法面板中可以看到已经创建了一个sp_singleresultset的方法,如下图:
然后打开Northwind.designer.cs,可以找到下面的代码:
[Function(Name=\ public ISingleResult sp_singleresultset() {
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod()))); return ((ISingleResult)(result.ReturnValue));
}
我们可以发现,IDE为这个存储过程单独生成了返回结果集的实体定义,你可能会觉得很奇怪,IDE怎么知道这个存储过程将会返回哪些数据那?其实,在把存储过程拖拽入dbml设计视图的时候,IDE就执行了类似下面的命令:
SET FMTONLY ON;
exec Northwind.dbo.sp_singleresultset SET FMTONLY OFF;
这样就可以直接获取存储过程返回的元数据而无须执行存储过程。 其实我们存储过程返回的就是顾客表的数据,如果你觉得为存储过程单独设置结果集实体有些浪费的话可以在存储过程的属性窗口中调整返回类型从“自动生成的类型”到Customer,不过以后你只能通过删除方法面板中的存储过程,然后重新添加来还原到“自动生成的类型”。下面,我们可以写如下的Linq to object代码进行查询:
var 单结果集存储过程 =
from c in ctx.sp_singleresultset()
where c.CustomerID.StartsWith(\ select c;
在这里确实是Linq to object的,因为查询句法不会被整句翻译成SQL,而是从存储过程的返回对象中再去对对象进行查询。SQL代码如下:
EXEC @RETURN_VALUE = [dbo].[sp_singleresultset]
-- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) [] 带参数的存储过程 创建如下存储过程:
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(\ Response.Write(rowcount);
ctx.sp_withparameter(\ Response.Write(rowcount);
结果输出了“01”。说明ID为“”的顾客数为0,而ID为“ALFKI”的顾客数为1。存储过程的输出参数被封装成了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) []
带返回值的存储过程 再来创建第三个存储过程:
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(\ 运行后程序输出“100101” 多结果集的存储过程
再来创建一个多结果集的存储过程:
create proc [dbo].[sp_multiresultset] as
set nocount on
select * from customers select * from employees
找到生成的存储过程方法:
[Function(Name=\ public ISingleResult sp_multiresultset() {
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod()))); return ((ISingleResult)(result.ReturnValue)); }
由于现在的VS2008会把多结果集存储过程识别为单结果集存储过程(只认识第一个结果集),我们只能对存储过程方法多小动手术,修改为:
[Function(Name=\ [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 emp.FirstName.Contains(\ GridView1.DataBind();
GridView2.DataSource = from c.CustomerID.StartsWith(\ GridView2.DataBind();
使用存储过程新增数据
存储过程除了可以直接调用之外,还可以用于实体的增删改操作。还记得在《一步一步学Linq to sql(三):增删改》中创建的留言簿程序吗?下面我们就来改
c
in
Customers
where
in
Employees
where