.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, 20),
                  new SqlParameter("@rt_msg", System.Data.SqlDbType.NVarChar, 200)    //输出一定要定义字符类型长度 以免报错
                };
            if (string.IsNullOrEmpty(strUpdateTime))
            { Param[0].Value = DBNull.Value; }
            else
            { Param[0].Value = strUpdateTime; }

 
            Param[1].Direction = ParameterDirection.Output;
            Param[2].Direction = ParameterDirection.Output;

           

            int numdata = await _DbContext.ExecuteNonQueryAsync("SP_AddDelUpdate", Param);
            string rtcode = Param[1].Value.ToString();
            string rtmessage = Param[2].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, 
                              '2018888888888888',
                              GETDATE() ,
                              1                       
                          );
    END;
    commit transaction
    set  @rt_code= '0000';
     set  @rt_msg= '执行成功!';
     return
     end try 
    begin catch
    set  @rt_code= '9999';
     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, 20),
                  new SqlParameter("@rt_msg", System.Data.SqlDbType.NVarChar, 200)    //输出一定要定义字符类型长度 以免报错
                };
            if (string.IsNullOrEmpty(strUpdateTime))
            { Param[0].Value = DBNull.Value; }
            else
            { Param[0].Value = strUpdateTime; }


            Param[1].Direction = ParameterDirection.Output;
            Param[2].Direction = ParameterDirection.Output;



            int numdata = await _DbContext.ExecuteNonQueryAsync("SP_AddDelUpdate", Param);
            string rtcode = Param[1].Value.ToString();
            string rtmessage = Param[2].Value.ToString();

            return numdata;

        }

 存储方法

 public async static Task<int> ExecuteNonQueryAsync(this DefaultDbContext db, string sql, SqlParameter[] sqlParams)
        {
            int numint=0;
            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, 20),
                  new SqlParameter("@rt_msg", System.Data.SqlDbType.NVarChar, 200)    //输出一定要定义字符类型长度 以免报错
                };
            if (string.IsNullOrEmpty(strUpdateTime))
            { Param[0].Value = DBNull.Value; }
            else
            { Param[0].Value = strUpdateTime; }


            Param[1].Direction = ParameterDirection.Output;
            Param[2].Direction = ParameterDirection.Output;



            int numdata = await _DbContext.ExecuteNonQueryAsync("SP_AddDelUpdate", Param);
            string rtcode = Param[1].Value.ToString();
            string rtmessage = Param[2].Value.ToString();
             var oParam = Param[Param.Length - 1];//返回最后一个输出参数
             
            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 = 0;
            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 = "201896666666666",
                    CityCode = "OO",
                    OrderStatus =8,
                    PayStatus = 0,
                    UpdateTime = DateTime.Now,
                    CreateTime = DateTime.Now,
                    UserID=2,

                };
              _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);
        }

 

posted @ 2018-05-25 11:51  蜜雪粮液  阅读(511)  评论(0编辑  收藏  举报