.NET MVC+ EF+通用存储过程实现增删改功能以及使用事物处理
引摘:
1、EF对事务进行了封装:无论何时执行任何涉及Create,Update或Delete的查询,都会默认创建事务。当DbContext类上的SaveChanges()方法被调用时,事务就会提交,saveChange()是有事务性的
2. 依赖多个不同的Context的操作(即分布式操作)或者多次调用context.saveChanges()操作,会脱离EF事务封装,此时可使用TransactionScope实现事务操作
选择合适的事务管理 下面一一对号入座:
1、如果只有一个DbContext类,那么应该尽力使用EF的默认事务管理。我们总应该将所有的操作组成一个在相同的DbContext对象的作用域中执行的工作单元,SaveChanges()方法会处理提交事务。
2、如果使用了多个DbContext对象,那么管理事务的最佳方法可能就是把调用放到TransactionScope对象的作用域中了。
3、如果要执行原生SQL,并想把这些操作和事务关联起来,那么应该使用EF提供的Database.BeginTransaction()方法。然而这种方法只支持EF6,不支持之前的版本。
4、EF 6起,EF在DbContext对象上提供了Database.BeginTransaction()方法,当使用上下文类在事务中执行原生SQL命令时,这个方法特别有用。
1、控制器实现
/// <summary>
/// 增删改 调用存储过程 返回json格式
/// </summary>
/// <returns></returns>
public async Task<ActionResult> AddORDelORUpdate()
{
string strUpdateTime =DateTime.Now.ToString();
SqlParameter[] Param =
{ //new SqlParameter("@UpdateTime", System.Data.SqlDbType.DateTime),
new SqlParameter("@UpdateTime", System.Data.SqlDbType.VarChar),
new SqlParameter("@rt_code", System.Data.SqlDbType.NVarChar, ),
new SqlParameter("@rt_msg", System.Data.SqlDbType.NVarChar, ) //输出一定要定义字符类型长度 以免报错
};
if (string.IsNullOrEmpty(strUpdateTime))
{ Param[].Value = DBNull.Value; }
else
{ Param[].Value = strUpdateTime; } Param[].Direction = ParameterDirection.Output;
Param[].Direction = ParameterDirection.Output; int numdata = await _DbContext.ExecuteNonQueryAsync("SP_AddDelUpdate", Param);
string rtcode = Param[].Value.ToString();
string rtmessage = Param[].Value.ToString(); return AsResult.Success(); }
2、存储过程
create PROCEDURE [dbo].[SP_AddDelUpdate]
(
@UpdateTime varchar(50),
@rt_code varchar(20) output,
@rt_msg nvarchar(200) output
)
AS
BEGIN
;
begin transaction
begin try
--if(@UpdateTime!=null)
BEGIN
update TRA_BargainOrder_Test set UpdateTime=@UpdateTime ; INSERT INTO TRA_BargainOrder_Test(
UserID,
CityCode,
UpdateTime,
BargainOrderCode,
CreateTime,
OrderStatus )
VALUES ( 3,
'SZ',
@UpdateTime,
'',
GETDATE() ,
1
);
END;
commit transaction
set @rt_code= '';
set @rt_msg= '执行成功!';
return
end try
begin catch
set @rt_code= '';
set @rt_msg= '失败,请稍候再试!';
rollback transaction
end catch
END
/// <summary>
/// 返回int类型 增删改 调用存储过程
/// </summary>
/// <returns></returns>
public async Task<int> Add_ORDelORUpdate()
{
string strUpdateTime = DateTime.Now.ToString();
SqlParameter[] Param =
{ //new SqlParameter("@UpdateTime", System.Data.SqlDbType.DateTime),
new SqlParameter("@UpdateTime", System.Data.SqlDbType.VarChar),
new SqlParameter("@rt_code", System.Data.SqlDbType.NVarChar, ),
new SqlParameter("@rt_msg", System.Data.SqlDbType.NVarChar, ) //输出一定要定义字符类型长度 以免报错
};
if (string.IsNullOrEmpty(strUpdateTime))
{ Param[].Value = DBNull.Value; }
else
{ Param[].Value = strUpdateTime; } Param[].Direction = ParameterDirection.Output;
Param[].Direction = ParameterDirection.Output; int numdata = await _DbContext.ExecuteNonQueryAsync("SP_AddDelUpdate", Param);
string rtcode = Param[].Value.ToString();
string rtmessage = Param[].Value.ToString(); return numdata; }
存储方法
public async static Task<int> ExecuteNonQueryAsync(this DefaultDbContext db, string sql, SqlParameter[] sqlParams)
{
int numint=;
using (var cmd = db.Database.Connection.CreateCommand())
{
try
{
await db.Database.Connection.OpenAsync();
cmd.CommandText = sql;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddRange(sqlParams); numint = await cmd.ExecuteNonQueryAsync();
cmd.Connection.Close(); }
catch (Exception ex)
{
_Logger.Error("执行数据" + ex.Message);
//throw new Exception("提交失败." + ex.Message);
}
finally
{
cmd.Connection.Dispose();
}
return numint; }
}
/// <summary>
/// 返回类型 增删改 调用存储过程 返回一个输出参数值
/// </summary>
/// <returns></returns>
public async Task<object> Add_ORDel_OR_Update()
{
string strUpdateTime = DateTime.Now.ToString();
SqlParameter[] Param =
{ //new SqlParameter("@UpdateTime", System.Data.SqlDbType.DateTime),
new SqlParameter("@UpdateTime", System.Data.SqlDbType.VarChar),
new SqlParameter("@rt_code", System.Data.SqlDbType.NVarChar, ),
new SqlParameter("@rt_msg", System.Data.SqlDbType.NVarChar, ) //输出一定要定义字符类型长度 以免报错
};
if (string.IsNullOrEmpty(strUpdateTime))
{ Param[].Value = DBNull.Value; }
else
{ Param[].Value = strUpdateTime; } Param[].Direction = ParameterDirection.Output;
Param[].Direction = ParameterDirection.Output; int numdata = await _DbContext.ExecuteNonQueryAsync("SP_AddDelUpdate", Param);
string rtcode = Param[].Value.ToString();
string rtmessage = Param[].Value.ToString();
var oParam = Param[Param.Length - ];//返回最后一个输出参数 return oParam; }
增删改操作使用事物处理 这个主要结合ado.net方式
/// <summary>
/// 异步执行带有参数的存储过程公共方法 增删改操作以及返回带有输出的参数 结合ADO.NET的事物处理
/// 这种情况,我们不能使用Database.BeginTransaction方法,因为我们需要将SqlConnection和SqlTransaction对象传给该函数,并把该函数放到我们的事务里。需要首先创建一个SqlConnection,然后开始SqlTransaction
/// </summary>
/// <param name="db"></param>
/// <param name="sql"></param>
/// <param name="sqlParams"></param>
/// <returns></returns>
public async static Task<int> ExecuteNonQueryAsync(this DefaultDbContext db, string sql, SqlParameter[] sqlParams)
{
var connectionString = ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString; int numint = ;
using (var conn = new SqlConnection(connectionString))
{
await conn.OpenAsync();
using (var dbContextTransaction = conn.BeginTransaction(System.Data.IsolationLevel.Snapshot))
{ try
{ var cmd = new SqlCommand();
using ( cmd.Connection = conn)
{ cmd.Transaction = dbContextTransaction;
cmd.CommandText = sql;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddRange(sqlParams); numint = await cmd.ExecuteNonQueryAsync();
//cmd.Connection.Close();
dbContextTransaction.Commit();
} // db.Database.UseTransaction(dbContextTransaction);
//using (var dbcontext =
// new DefaultDbContext(conn, contextOwnsConnection: false))
//{
// dbcontext.Database.UseTransaction(dbContextTransaction); // //dbcontext.SaveChanges();
//}
//dbContextTransaction.Commit(); }
catch (Exception ex)
{
dbContextTransaction.Rollback();
_Logger.Error("执行数据" + ex.Message); }
finally
{
dbContextTransaction.Dispose();
}
return numint;
}
}
}
单个savechanges上下文实现事务 Database.BeginTransaction
public ActionResult Index()
{
var dbContextTransaction = _DbContext.Database.BeginTransaction();
try
{
TRA_BargainOrder_Test TRA = new TRA_BargainOrder_Test
{
BargainOrderCode = "",
CityCode = "OO",
OrderStatus =,
PayStatus = ,
UpdateTime = DateTime.Now,
CreateTime = DateTime.Now,
UserID=, };
_DbContext.TRA_BargainOrders.Add(TRA);
} _DbContext.SaveChanges();
dbContextTransaction.Commit();
}
catch(Exception ex)
{
dbContextTransaction.Rollback();
_Logger.Error("执行数据" + ex.Message);
}
finally
{
dbContextTransaction.Dispose();
}
var data = _DbContext.TRA_BargainOrders.ToList(); return View(data);
}
.NET MVC+ EF+通用存储过程实现增删改功能以及使用事物处理的更多相关文章
- ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK
看到本文的标题,相信你会忍不住进来看看! 没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询, 加入一个表10W数据,另一个表也是10万数据,当你用linq建立一个连接查询 ...
- Ibatis调用存储过程实现增删改以及分页查询
1.Ibatis实现增删改操作很简单了,通常我是将某一模块的增删改功能写在一个存储过程里,通过一个标识符去区分执行增加还是修改抑或删除操作. statement: <!-- 存储过程:实现学生的 ...
- MVC创建XML,并实现增删改
原文:MVC创建XML,并实现增删改 如果创建如下的XML: <?xml version="1.0" encoding="utf-8" standalon ...
- ASP.NET MVC + EF 利用存储过程读取大数据
ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK 看到本文的标题,相信你会忍不住进来看看! 没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询, ...
- oracle-扫盲贴:存储过程实现增删改查
原文引入:http://blog.csdn.net/yangzhawen/article/details/8617179 oracle-扫盲贴:存储过程实现增删改查 分类: oracle2013-02 ...
- .NET MVC+ EF+调用存储过程 多表联查以及VIEW列表显示
直接上干活,至于网上的一大堆处理方式不予评论,做好自己的就是最好的,供大家不走弯路 1.view页面 <link href="~/Content/bootstrap.css" ...
- Asp.net MVC4 使用EF实现数据库的增删改查
EF的使用 步骤: (1)将EF添加到项目:在Model右击添加新建项 找到ADO.NET实体数据模型,接着... (2)实现数据库的增删改查 查询 (因为在Model中已经添加EF实体了 ...
- 使用EF实现数据库的增删改查
EF的使用步骤:(1)将EF添加到项目:在Model右击添加新建项找到ADO.NET实体数据模型,接着…(2)实现数据库的增删改查查询(因为在Model中已经添加EF实体了,所以就可以在Control ...
- MVVM架构~knockoutjs与MVC配合,实现列表的增删改功能
返回目录 MVC与MVVM的模型 在MVC实例项目中,为我们提供了简单的增删改查功能,而这种功能的实现与具体的Model很有关系,或者说它与后台数据库的关系过于紧密了,而对于开发人员来说当页面布局修改 ...
随机推荐
- 主成分分析PCA
PCA(Principal Component Analysis)不仅仅是对高维数据进行降维,更重要的是经过降维去除了噪声,发现了数据中的模式. PCA把原先的n个特征用数目更少的m个特征取代,新特征 ...
- UAC 实现原理及绕过方法
目录 0x00 UAC 工作流程 0x01 UAC 实现方法(用户登陆过程) 0x02 UAC 架构 0x03 触发UAC 0x04 UAC 虚拟化 0x05 UAC 逆向分析 1x00 UAC By ...
- 共享内存:mmap函数实现
内存映射的应用: 以页面为单位,将一个普通文件映射到内存中,通常在须要对文件进行频繁读写时使用,这样用内存读写代替I/O读写,以获得较高的性能; 将特殊文件进行匿名内存映射,能够为关联进程提供共享内存 ...
- android使用GestureDetector实现手势下滑关闭页面的效果。
实现类似Android风云直播手机端注册登录页,当手势向下滑动的时候,关闭页面的效果. 使用GestureDetector来实现这个效果,当手势在屏幕上面滑动的时候 ,会掉用onFling方法,所以, ...
- Python实现:十进制数与(2~16进制数)之间的互相转换
(最开始源于牛客网上的一道编程题 : [编程题] 数制转换) 将X进制转为int十进制的功能函数:(乘X次方各位数的加和法) # 将X进制转为int十进制的功能函数:(乘X次方各位数的加和法) def ...
- android开发学习---基础知识学习、如何导入已有项目和开发一个电话拨号器
一.基础知识点学习 1.Android体系结构 如图所示,android 架构分为三层: (1)最底层是linux内核,主要是各种硬件的驱动,如相机驱动(Camera Driver),闪存驱动(Fl ...
- 运维自动化之Cobbler系统安装使用详解[good]
一.简介 Cobbler是一个快速网络安装linux的服务,而且在经过调整也可以支持网络安装windows.该工具使用python开发,小巧轻便(才15k行python代码),使用简单的命令即可完成P ...
- 树莓派进阶之路 (007) - 树莓派安装cmake3.5 脚本(原创)
cmake3.5安装脚本: #!/bin/bash cd echo "安装make" sudo apt-get install make echo "安装cmake&qu ...
- EF的表左连接方法Include和Join
在EF中表连接常用的有Join()和Include(),两者都可以实现两张表的连接,但又有所不同. 例如有个唱片表Album(AlbumId,Name,CreateDate,GenreId),表中含外 ...
- OpenCV 学习笔记03 findContours函数
opencv-python 4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ...