目录

写在前面

文档与系列文章

Nhibernate中使用存储过程

一个例子

总结

写在前面

上篇文章一个小插曲,分析了延迟加载是如何解决N+1 select查询问题的。这篇开始介绍在nhibernate中如何使用存储过程,同时也介绍如何使用代码生成器,提高开发效率。

文档与系列文章

[Nhibernate]体系结构

[NHibernate]ISessionFactory配置

[NHibernate]持久化类(Persistent Classes)

[NHibernate]O/R Mapping基础

[NHibernate]集合类(Collections)映射 

[NHibernate]关联映射

[NHibernate]Parent/Child

[NHibernate]缓存(NHibernate.Caches)

[NHibernate]NHibernate.Tool.hbm2net

[NHibernate]Nullables

[NHibernate]Nhibernate如何映射sqlserver中image字段

[NHibernate]基本配置与测试 

[NHibernate]HQL查询 

[NHibernate]条件查询Criteria Query

[NHibernate]增删改操作

[NHibernate]事务

[NHibernate]并发控制

[NHibernate]组件之依赖对象

[NHibernate]一对多关系(级联删除,级联添加)

[NHibernate]一对多关系(关联查询)

[NHibernate]多对多关系(关联查询)

[NHibernate]延迟加载

[NHibernate]立即加载

[NHibernate]视图处理

[NHibernate]N+1 Select查询问题分析

Nhibernate中使用存储过程

这里使用MyGeneration Code来生成针对TB_Customer数据表的增删改的存储过程。MyGeneration Code是一款开源的代码生成器,下载地址MyGeneration Code。

安装完成后,打开MyGeneration,如果第一次使用MyGeneration会自动弹出“默认设置”对话框,需要你对MyGeneration设置数据库连接字符串、模板语言、数据库驱动、模板存放路径等信息。

然后选择“save”对默认配置进行保存。然后MyGenration主界面就会弹出。如图

展开Microsoft SQL Server节点,找到“Script Insert/Update/Delete Procedures for SQL Server”模板,右击选择执行,我们利用这个模板为Customer表生成增删改存储过程。

打开后,这个模板界面如下,选择输出路径和数据库表,这里我输入路径为桌面,选择TB_Customer表,点击OK。截图如下:

此时在桌面“C:\Users\Wolfy\Desktop\Customer”中就会生成sql_procs_TB_Customer.sql文件,打开数据库,然后执行该文件中的sql脚本。

 USE [Shop]
GO --|--------------------------------------------------------------------------------
--| [TB_CustomerInsert] - Insert Procedure Script for TB_Customer
--|--------------------------------------------------------------------------------
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[TB_CustomerInsert]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1) DROP PROCEDURE [dbo].[TB_CustomerInsert]
GO CREATE PROCEDURE [dbo].[TB_CustomerInsert]
(
@CustomerID uniqueidentifier = NEWID() OUTPUT,
@CustomerName nvarchar(16) = NULL,
@CustomerAddress nvarchar(128) = NULL,
@Version int
)
AS
SET NOCOUNT ON INSERT INTO [TB_Customer]
(
[CustomerID],
[CustomerName],
[CustomerAddress],
[Version]
)
VALUES
(
@CustomerID,
@CustomerName,
@CustomerAddress,
@Version
) RETURN @@Error
GO --|--------------------------------------------------------------------------------
--| [TB_CustomerUpdate] - Update Procedure Script for TB_Customer
--|--------------------------------------------------------------------------------
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[TB_CustomerUpdate]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1) DROP PROCEDURE [dbo].[TB_CustomerUpdate]
GO CREATE PROCEDURE [dbo].[TB_CustomerUpdate]
(
@CustomerID uniqueidentifier,
@CustomerName nvarchar(16) = NULL,
@CustomerAddress nvarchar(128) = NULL,
@Version int
)
AS
SET NOCOUNT ON UPDATE [TB_Customer]
SET
[CustomerID] = @CustomerID,
[CustomerName] = @CustomerName,
[CustomerAddress] = @CustomerAddress,
[Version] = @Version
WHERE
[CustomerID] = @CustomerID RETURN @@Error
GO --|--------------------------------------------------------------------------------
--| [TB_CustomerDelete] - Update Procedure Script for TB_Customer
--|--------------------------------------------------------------------------------
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[TB_CustomerDelete]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1) DROP PROCEDURE [dbo].[TB_CustomerDelete]
GO CREATE PROCEDURE [dbo].[TB_CustomerDelete]
(
@CustomerID uniqueidentifier
)
AS
SET NOCOUNT ON DELETE
FROM [TB_Customer]
WHERE
[CustomerID] = @CustomerID RETURN @@Error
GO

sql_procs_TB_Customer.sql

我使用的是sql server2012的版本,在执行脚本的时候,生成添加Customer的存储过程,有问题

将NewId()函数去掉。修改后的存储过程

 USE [Shop]
GO
--|--------------------------------------------------------------------------------
--| [TB_CustomerInsert] - Insert Procedure Script for TB_Customer
--|--------------------------------------------------------------------------------
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[TB_CustomerInsert]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1) DROP PROCEDURE [dbo].[TB_CustomerInsert]
GO CREATE PROCEDURE [dbo].[TB_CustomerInsert]
(
@CustomerID uniqueidentifier OUTPUT,
@CustomerName nvarchar(16) = NULL,
@CustomerAddress nvarchar(128) = NULL,
@Version int
)
AS
SET NOCOUNT ON INSERT INTO [TB_Customer]
(
[CustomerID],
[CustomerName],
[CustomerAddress],
[Version]
)
VALUES
(
NEWID(),
@CustomerName,
@CustomerAddress,
@Version
) RETURN @@Error

生成的存储过程如下:

一个例子

在NHibernate的映射文件中,在Class元素中提供了<sql-delete>、<sql-insert>、<sql-update>元素用于删除、新建、更新对象,注意这三个元素顺序唯一,就是下图显示的顺序,在根元素提供了<sql-query>元素用来查询对象,下图显示在Class元素中的增删改存储过程元素。

删除对象

修改映射文件添加存储过程,打开Customer.hbm.xml映射文件,在Class元素下添加<sql-delete>节点,调用TB_CustomerDelete存储过程,TB_CustomerDelete存储过程有一个CustomerID参数,这里用一个问号表示:

    <!--存储过程,check参数:none/rowcount/param-->
<sql-delete>exec TB_CustomerDelete ?</sql-delete>

测试

         /// <summary>
/// 通过存储过程方式删除客户信息
/// </summary>
/// <param name="customer"></param>
/// <returns></returns>
public bool DeleteCustomerByIDWithProcedure(Customer customer)
{
var session = NHibernateHelper.GetSession();
using (ITransaction trans = session.BeginTransaction())
{
try
{
session.Delete(customer);
session.Flush();
trans.Commit();
return true;
}
catch (Exception)
{
trans.Rollback();
throw;
}
}
}

此时会有一个异常“Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Wolfy.Shop.Domain.Entities.Customer#b0720295-9541-40b3-9994-610066224db8]”。这个错误是存储过程写法错误,我们修改TB_CustomerDelete存储过程,去掉SET NOCOUNT ON,代码片段如下:

 ALTER PROCEDURE [dbo].[TB_CustomerDelete]
(
@CustomerID uniqueidentifier
)
AS
--SET NOCOUNT ON DELETE
FROM [TB_Customer]
WHERE
[CustomerID] = @CustomerID RETURN @@Error

再次运行进行测试,测试成功,查看生成的sql语句

你会发现在sql语句里面多了一个@p1的参数。这个参数为之前添加的Version参数,nhibernate中乐观并发控制添加的。

如何解决?

修改存储过程,将版本号添加上。

 ALTER PROCEDURE [dbo].[TB_CustomerDelete]
(
@CustomerID uniqueidentifier,
@Version int
)
AS
--SET NOCOUNT ON DELETE
FROM [TB_Customer]
WHERE
[CustomerID] = @CustomerID and [Version]=@Version RETURN @@Error

不要忘了,此时的存储过程有两个参数了,版本号在映射文件中已经处理了,存储过程中已经帮咱们自动添加上了,如果是其他的参数可在映射文件通过"?,?..."添加多个参数。

    <!--存储过程,check参数:none/rowcount/param-->
<sql-delete check="rowcount" >exec TB_CustomerDelete ?</sql-delete>

再次运行进行测试,成功,生成的sql语句

exec sp_executesql N'exec TB_CustomerDelete @p0',N'@p0 uniqueidentifier,@p1 int',@p0='3727A133-C079-4DF9-B31E-7625B03F95DF',@p1=1

当然了,如果你不想使用存储过程,也可以直接在<sql-delete>中写SQL语句,像这样,照样用。

  <sql-delete>DELETE FROM [TB_Customer] WHERE [CustomerID] = ? and [Version] =?</sql-delete>

生成的sql语句为

exec sp_executesql N'DELETE FROM [TB_Customer] WHERE [CustomerID] = @p0 and [Version] =@p1',N'@p0 uniqueidentifier,@p1 int',@p0='64C35DEE-84D9-4C2D-ABAF-7D53631E3EAA',@p1=1

总结

这篇文章主要介绍了代码生成器的简单使用及nhibernate中使用存储过程删除数据的过程。

参考文章:http://www.cnblogs.com/lyj/archive/2008/11/03/1325291.html

[NHibernate]存储过程的使用(一)的更多相关文章

  1. [NHibernate]存储过程的使用(二)

    目录 写在前面 文档与系列文章 创建对象 更新对象 总结 写在前面 上篇文章介绍了如何使用MyGeneration代码生成器生成存储过程,以及nhibernate中通过存储过程删除数据的内容,这篇文章 ...

  2. [NHibernate]存储过程的使用(三)

    目录 写在前面 文档与系列文章 查询 总结 写在前面 前面的文章介绍了在nhibernate中使用存储过程进行增删改的操作,当然查询也是可以的,在nhibernate中也可以执行任意的存储过程.本篇文 ...

  3. NHibernate 存储过程使用

    NHibernate也是能够操作存储过程的,不过第一次配置可能会碰到很多错误. 一.删除 首先,我们新建一个存储过程如下: CREATE PROC DeletePerson @Id int AS DE ...

  4. Nhibernate 存储过程获取返回值

    写在前面:因为项目使用ssh.net所以做着做着要调用存储过程,而且是有返回值的,按照以前的做法直接在参数里指定下就可以获取,但是在nhibernate里调用就有点陌生了,百度一下得出的结果有两种:第 ...

  5. NHibernate 存储过程 第十四篇

    NHibernate也是能够操作存储过程的,不过第一次配置可能会碰到很多错误. 一.删除 首先,我们新建一个存储过程如下: CREATE PROC DeletePerson @Id int AS DE ...

  6. 转:NHibernate 存储过程

    http://stackoverflow.com/questions/928847/how-to-get-the-return-value-from-a-sql-server-stored-proce ...

  7. [Nhibernate]SchemaExport工具的使用(二)——创建表及其约束、存储过程、视图

    目录 写在前面 文档与系列文章 表及其约束 存储过程 视图 总结 写在前面 由于一直在山西出差,有几天没更新博客了.昨晚回到家,将博客园最近三天更新的文章搜集了一下,花费了半天的时间,看了看,有些文章 ...

  8. 耗时两月,NHibernate系列出炉

    写在前面 这篇总结本来是昨天要写的,可昨天大学班长来视察工作,多喝了点,回来就倒头就睡了,也就把这篇总结的文章拖到了今天. nhibernate系列从开始着手写,到现在前后耗费大概两个月的时间,通过总 ...

  9. [NHibernate]代码生成器的使用

    目录 写在前面 文档与系列文章 代码生成器的使用 总结 写在前面 前面的文章介绍了nhibernate的相关知识,都是自己手敲的代码,有时候显得特别的麻烦,比如你必须编写持久化类,映射文件等等,举得例 ...

随机推荐

  1. Linux下通配符总结

    * - 通配符,代表任意字符(0到多个)? - 通配符,代表一个字符# - 注释/ - 跳转符号,将特殊字符或通配符还原成一般符号| - 分隔两个管线命令的界定; - 连续性命令的界定~ - 用户的根 ...

  2. 使用ab进行压力测试详解

    ab是apache自带的压力测试工具,非常好用.转载几篇对ab工具的详细使用的博文.猛击下面的链接地址 http://www.365mini.com/page/apache-benchmark.htm ...

  3. Invalid layout param in a LinarLayout: layout_weight

    android:layout_weight只适用于线性布局LinearLayout,不适用于相对布局RelativeLayout.

  4. J2EE基础之Servlet

    J2EE基础之Servlet 1.  什么是Servlet? Servlet即Java服务小程序,是使用应用程序设计接口以及相关类和方法的Java程序.它可以作为一种插件,像Applet程序一样嵌入到 ...

  5. JSP连接MySQL数据库问题

    之前写了一大段,还说了一下具体JDBC连接数据库API的具体包的基本知识,哪知道自己手残不小心按了删除按钮.结果去看自动保存记录时,就只剩下下面这段了.好吧,其实最主要最核心的也就是下面这点了.具体如 ...

  6. OpenCV 之 编译和配置

    “工欲善其事,必先利其器”,下面介绍在 Win7 32位系统下,用 cmake 编译 OpenCV 的过程. 1  开发环境 1.1  Win7 Windows 7 家庭普通版,Service Pac ...

  7. [转载]python:open/文件操作

    open/文件操作f=open('/tmp/hello','w') #open(路径+文件名,读写模式) #读写模式:r只读,r+读写,w新建(会覆盖原有文件),a追加,b二进制文件.常用模式 如:' ...

  8. mysql 加锁测试

    今天研究cobar,做执行时间测试,需要对表记录加锁.用了以下两种方式为表记录加锁. 第一种方式: begin;    //开始事务 select * from 表名 ( where ……) for ...

  9. 百度数据可视化图表套件echart实战

    最近我一直在做数据可视化的前端工作,我用的最多的绘图工具是d3.d3有点像photoshop,功能很强大,例子也很多,但是学习成本也不低,做项目是需要较大人力投入的.3月底由在亚马逊工作的同学介绍下使 ...

  10. centos7.0 安装字体库

    最近在centos7.0下用itextpdf将word文档转成pdf时出现字体丢失的情况.网上找了很多资料,各式各样的原因和解决方法.后来经过一番测试发现是centos7.0 minimal没有安装相 ...