引摘:

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+通用存储过程实现增删改功能以及使用事物处理的更多相关文章

  1. ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK

    看到本文的标题,相信你会忍不住进来看看! 没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询, 加入一个表10W数据,另一个表也是10万数据,当你用linq建立一个连接查询 ...

  2. Ibatis调用存储过程实现增删改以及分页查询

    1.Ibatis实现增删改操作很简单了,通常我是将某一模块的增删改功能写在一个存储过程里,通过一个标识符去区分执行增加还是修改抑或删除操作. statement: <!-- 存储过程:实现学生的 ...

  3. MVC创建XML,并实现增删改

    原文:MVC创建XML,并实现增删改 如果创建如下的XML: <?xml version="1.0" encoding="utf-8" standalon ...

  4. ASP.NET MVC + EF 利用存储过程读取大数据

    ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK 看到本文的标题,相信你会忍不住进来看看! 没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询, ...

  5. oracle-扫盲贴:存储过程实现增删改查

    原文引入:http://blog.csdn.net/yangzhawen/article/details/8617179 oracle-扫盲贴:存储过程实现增删改查 分类: oracle2013-02 ...

  6. .NET MVC+ EF+调用存储过程 多表联查以及VIEW列表显示

    直接上干活,至于网上的一大堆处理方式不予评论,做好自己的就是最好的,供大家不走弯路 1.view页面 <link href="~/Content/bootstrap.css" ...

  7. Asp.net MVC4 使用EF实现数据库的增删改查

    EF的使用 步骤: (1)将EF添加到项目:在Model右击添加新建项 找到ADO.NET实体数据模型,接着... (2)实现数据库的增删改查       查询 (因为在Model中已经添加EF实体了 ...

  8. 使用EF实现数据库的增删改查

    EF的使用步骤:(1)将EF添加到项目:在Model右击添加新建项找到ADO.NET实体数据模型,接着…(2)实现数据库的增删改查查询(因为在Model中已经添加EF实体了,所以就可以在Control ...

  9. MVVM架构~knockoutjs与MVC配合,实现列表的增删改功能

    返回目录 MVC与MVVM的模型 在MVC实例项目中,为我们提供了简单的增删改查功能,而这种功能的实现与具体的Model很有关系,或者说它与后台数据库的关系过于紧密了,而对于开发人员来说当页面布局修改 ...

随机推荐

  1. Jmeter+maven+Jenkins构建云性能测试平台(mark 推荐)

    转自:http://www.cnblogs.com/victorcai0922/archive/2012/06/20/2555502.html Jmeter+maven+Jenkins构建云性能测试平 ...

  2. 代理服务 SQUID 测试

    第一部分:SQUID基础 Squid代理服务的基本配置: http_port 3128                    #设置监听的IP与端口号 cache_mem 64 MB          ...

  3. Quartz.NET开源作业调度框架系列(三):IJobExecutionContext 参数传递-转

    前面写了关于Quartz.NET开源作业调度框架的入门和Cron Trigger , 这次继续这个系列, 这次想讨论一下Quartz.NET中的Job如何通过执行上下文(Execution Conte ...

  4. 给我一对公钥和私钥,我就能破解此RSA

    RSA密码系统如果暴露了一套公钥和私钥,那么这套密码系统就全部失效了.因为根据公钥和私钥可以完成大整数的分解.暴露了两个质数. 记公钥为e,私钥为d,因为ed%phi=1,所以就得到了一个k=ed-1 ...

  5. Android开发环境——调试器 DDMS相关内容汇总

       Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT ...

  6. mysql--SQL编程(基础知识) 学习笔记1

    1.数据库应用类型分类: 一般来说,可将数据库的应用类型分为OLTP(OnLine TransactionProcessing ,联机事务处理)和OLAP(OnLine Analysis Proces ...

  7. 树莓派(raspberry pi)学习11: 将树莓派变成一个Web服务器(转)

    将树莓派变成一个Web服务器,通过访问网页,就可以控制树莓派,比如:查看摄像头\开灯等等. 一想到Linux Web服务器,我们首先想到的是,Apache + MySql + Php. 树莓派可以安装 ...

  8. Ubuntu14.04安装CMake3.5.1(转)

    1.下载cmake-3.5.1.tar.gz:https://cmake.org/download/ 2.把 cmake-3.5.1.tar.gz放到任意临时目录(因为Cmake的安装路径默认在:/u ...

  9. Linux操作系统中文件结构stat中st_size的说明以及对于文件中洞(Holes)的理解

    文件stat结构体中st_size成员 对于所有的文件类型,st_size成员对其中的普通文件.目录以及符号链接有实在的意义.其中,对于普通文件而言,st_size记录了该文件的实际大小:对于目录而言 ...

  10. ROS学习(七)—— 理解ROS Topic

    一.准备工作 1.打开roscore roscore 2.turtlesim 打开一个turtulesim节点 rosrun turtlesim turtlesim_node 3.turtle key ...