首页 > 解决方案 > C# Sql 从对象列表中逐行更新

问题描述

public int UpdateAmount(List<MyTable> myBizObjList)
     {
         SqlTransaction sqltxn;
         DbClass db = new DbClass();
         SqlConnection cs;
         cs = db.GetConnection();

         string commandText = @"Update MyTable Set amt = @amt  where empno = @empno and mydate = @mydate";

         int x = myBizObjList.Count;
         int y = 0,rowsaffected;
         cs.Open();

         using (cs)
         {
             sqltxn = cs.BeginTransaction();
             foreach (MyTable myBizObj in myBizObjList)
              { 
                 SqlCommand command = new SqlCommand(commandText, cs, sqltxn);
                 command.Parameters.Add("@empno", SqlDbType.Int);
                 command.Parameters["@empno"].Value = myBizObj.Empno;
                 command.Parameters.Add("@mydate", SqlDbType.Date);
                 command.Parameters["@mydate"].Value = myBizObj.Mydate;
                 command.Parameters.Add("@amt", SqlDbType.Decimal);
                 command.Parameters["@amt"].Value = myBizObj.Amt;
                                 
                 
                 try
                 {
                     rowsAffected = command.ExecuteNonQuery();
                     if (rowsAffected == 1)
                         y++;
                 }
                 catch (Exception ex)
                 {
                     throw (ex);
                    
                 }
             }
             if (y == x)
             {
                 sqltxn.Commit();
                 
             }
             else
             {
                sqltxn.Rollback();
                 y = 0;
             }
             cs.Close();
             return y;
         }
         
     }

问题:我正在查询一个表并得到说我正在转换为对象列表的 50K 记录。我正在处理我的 BLL 中的列表并发送到我的 DAL。以上是我的 DAL 中的一个方法。有没有更好的办法?我还在检查是否所有行都已更新,然后是 Commit 或 Rollback。

标签: c#

解决方案


您可以将其转换为表值参数。

首先我们需要一个表类型:

CREATE TYPE dbo.MyTVP (
    empno int not null,
    mydate date not null,
    amt decimal not null
    primary key (empno, mydate)
);

然后我们通过它。您不一定需要存储过程,您可以将其作为临时批处理执行:

public int UpdateAmount(List<MyTable> myBizObjList)
     {
         var table = new DataTable();
         table.Columns.Add("empno", typeof(int));
         table.Columns.Add("mydate", typeof(datetime));
         table.Columns.Add("amt", typeof(decimal));
         foreach (MyTable myBizObj in myBizObjList)
             table.Rows.Add(myBizObj.Empno, myBizObj.Mydate, myBizObj.Amt);
         
         const string commandText = @"
Update tbl
Set amt = t.amt
FROM MyTable AS tbl
JOIN @tmp AS t ON t.empno = tbl.empno AND t.mydate = tbl.mydate;
";

         using (var cs = db.GetConnection())
         {
             SqlCommand command = new SqlCommand(commandText, cs, sqltxn);
             command.Parameters.Add(
             new SqlParameter("@tmp", SqlDbType.Structured)
             {
                 Direction = ParameterDirection.Input,
                 TypeName = "dbo.MyTVP",
                 Value = table
             });

             cs.Open();
             return command.ExecuteNonQuery();
         }
     }

推荐阅读