NHibernate之(15):探索NHibernate中使用存储过程(上)
本节内容
- 引入
- 使用MyGeneration生成存储过程
- 实例分析
- 1.删除对象
- 结语
返回文章列表
引入
上一篇,我们介绍了视图,征集大家的意见,我接下来可能用三篇篇幅来介绍在NHibernate中如何使用存储过程的整个详细过程,这些全是在实际运用中积累的经验,涉及刚刚使用的错误信息,如何修改存储过程,并且比较没有使用存储过程的不同点,并非官方比较权威的资料,所以敬请参考。
使用MyGeneration生成存储过程
由于写存储过程不是这节的重点,我们来利用MyGeneration代码生成工具来利用为Customer表生成插入、更新、删除记录的存储过程。顺便也来学习MyGeneration开源的生成器怎么用的,如果你还没有,请到这里下载安装。
安装完之后,打开MyGeneration,如果你第一次使用MyGeneration会自动弹出“默认设置”对话框,需要你对MyGeneration设置数据库连接字符串、模板语言、数据库驱动、模板存放路径等信息,截图如下(由于这篇图片比较多,点击图片放大):
我们要首先配置数据库连接字符串,如果你对手写感兴趣,你可以直接在文本框中修改具体字符串;如果你和我一样,就点击“OLEDB...”按钮利用界面配置连接字符串,点击按钮之后,出来“数据连接属性”对话框,中文的哦,MyGeneration直接调用SQL Server的配置对话框,按下面图示,填写自己的连接字符串信息:
然后点击“确定”,这个对话框的连接信息将保存在“默认配置”对话框中,点击“Save”保存配置信息。
这时,MyGeneration主界面就打开了,点击工具栏的第三个按钮,打开“模板浏览器”窗口,截图如下:
展开Microsoft SQL Server节点,找到“Script Insert/Update/Delete Procedures for SQL Server”模板,右击选择执行,我们利用这个模板为Customer表生成增删改存储过程。
打开后,这个模板界面如下,选择输出路径和数据库表,这里我输入路径为桌面,选择Customer表,点击OK。截图如下:
这时在桌面上生成sql_procs_Customer.sql文件,打开SQL Server Management Studio执行这个SQL脚本,展开NHibernateSample表下的存储过程,已经出来了三个存储过程,分别是CustomerDelete、CustomerInsert、CustomerUpdate。
好了,我们使用MyGeneration生成存储过程,这个工作完成了,但是噩梦开始了......
实例分析
还是一步一步来,依次从删除对象、新建对象、更新对象、查询对象来介绍在NHibernate中如何使用存储过程的整个详细过程。在NHibernate的映射文件中,在Class元素中提供了<sql-delete>、<sql-insert>、<sql-update>元素用于删除、新建、更新对象,注意这三个元素顺序唯一,就是下图显示的顺序,在根元素提供了<sql-query>元素用来查询对象,下图显示在Class元素中的增删改存储过程元素。
1.删除对象
这篇数据访问层中代码我们使用NHibernate之旅(6):探索NHibernate中的事务中的代码,测试代码在NHibernate之旅(5):探索Insert, Update, Delete操作中体现,无需任何改动。
Step1:为了比较,我们先执行DeleteCustomerTest()测试方法,没有使用存储过程下删除对象生成SQL语句如下:
DELETE FROM Customer WHERE CustomerId = @p0 AND Version = @p1; @p0 = '7', @p1 = '1'
Step2:修改映射文件添加存储过程,打开Customer.hbm.xml映射文件,在Class元素下添加<sql-delete>节点,调用CustomerDelete存储过程,CustomerDelete存储过程有一个CustomerId参数,这里用一个问号表示:
<sql-delete>exec CustomerDelete ?</sql-delete>
Step3:执行DeleteCustomerTest()测试方法,出现错误“NHibernate.StaleObjectStateException : Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [DomainModel.Entities.Customer#4]”,这个错误是存储过程写法错误,我们修改CustomerDelete存储过程,去掉SET NOCOUNT ON,代码片段如下:
ALTER PROCEDURE [dbo].[CustomerDelete] ( @CustomerId int ) AS --SET NOCOUNT ON DELETE FROM [Customer] WHERE [CustomerId] = @CustomerId RETURN @@Error
Step4:执行DeleteCustomerTest()测试成功,NHibernate生成语句如下:
exec CustomerDelete @p0; @p0 = '6', @p1 = '1'
恩,成功了,但是在看看存储过程,想想存储过程中写的SQL语句,和没有使用存储过程,NHibernate生成的SQL语句有些不同,显然没有顾及到版本控制问题,使用存储过程NHibernate生成语句无缘无故增加了一个参数@p1,我们来解决一下:
Step5:修改存储过程添加Version处理:
ALTER PROCEDURE [dbo].[CustomerDelete] ( @CustomerId int, @Version int ) AS DELETE FROM [Customer] WHERE [CustomerId] = @CustomerId and [Version] = @Version RETURN @@Error
Step6:执行DeleteCustomerTest()测试,发生错误:“过程或函数 'CustomerDelete' 需要参数 '@Version',但未提供该参数。” 哦,原来映射文件参数数量没有改。
Step7:修改存储过程参数数量,打开映射文件在<sql-delete>中添加一个参数即添加“,?”
<sql-delete>exec CustomerDelete ?,?</sql-delete>
Step8:最后执行DeleteCustomerTest()测试成功,NHibernate生成SQL语句如下,和NHibernate没有使用存储过程一样了,考虑了版本控制问题,完全符合。OK!!
exec CustomerDelete @p0,@p1; @p0 = '8', @p1 = '1'
当然了,如果你不想使用存储过程,也可以直接在<sql-delete>中写SQL语句,像这样,照样用。
<sql-delete>DELETE FROM [Customer] WHERE [CustomerId] = ? and [Version] =?</sql-delete>
结语
这篇就说到这里了,主要学习怎么使用MyGeneration提供的模板创建存储过程和删除对象存储过程的使用,下篇继续创建、更新、查询对象存储过程的使用。
下次继续分享NHibernate!