引摘:
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);
}