C# 多个数据库更新:

C# 多个数据库更新:,c#,.net,sql-server,C#,.net,Sql Server,取代问题: 下面是更新考试结果集的代码片段。 DB结构是给定的,但我可以提交存储过程以供包含(这是一个很难修改的问题,所以我将其保存到最后) 问题是:有没有更好的方法使用SQLServerv2005.NET2.0 string update = @"UPDATE dbo.STUDENTAnswers SET ANSWER=@answer WHERE StudentID =@I

取代问题:

下面是更新考试结果集的代码片段。 DB结构是给定的,但我可以提交存储过程以供包含(这是一个很难修改的问题,所以我将其保存到最后)

问题是:有没有更好的方法使用SQLServerv2005.NET2.0

string update = @"UPDATE dbo.STUDENTAnswers 
                              SET ANSWER=@answer
                              WHERE StudentID =@ID and QuestionNum =@qnum";
            SqlCommand updateCommand = new SqlCommand( update, conn );
            conn.Open();

            string uid = Session["uid"].ToString();
            for (int i= tempStart; i <= tempEnd; i++)
            {
                updateCommand.Parameters.Clear();
                updateCommand.Parameters.AddWithValue("@ID",uid);
                updateCommand.Parameters.AddWithValue("@qnum",i);
                updateCommand.Parameters.AddWithValue("@answer", Request.Form[i.ToString()]);
                try
                {
                    updateCommand.ExecuteNonQuery();
                }
                catch { }
            }
string update=@“update dbo.STUDENTAnswers
SET ANSWER=@ANSWER
其中StudentID=@ID,QuestionNum=@qnum”;
SqlCommand updateCommand=新的SqlCommand(更新,连接);
conn.Open();
字符串uid=Session[“uid”].ToString();

对于(int i=tempStart;i发出与值表相反的单个更新:

UPDATE s SET ANSWER=a FROM dbo.STUDENTAnswers s JOIN (
  SELECT 1 as q, 'answer1' as a
  UNION ALL SELECT 2, 'answer2' -- etc...
) x ON s.QuestionNum=x.q AND StudentID=@ID
所以你就这样把这些放在一起:

using(SqlCommand updateCommand = new SqlCommand()) {
  updateCommand.CommandType = CommandType.Text;
  updateCommand.Connection = conn;
  if (cn.State != ConnectionState.Open) conn.Open();

  StringBuilder sb = new StringBuilder("UPDATE s SET ANSWER=a FROM dbo.STUDENTAnswers s JOIN (");
  string fmt = "SELECT {0} as q, @A{0} as a";
  for(int i=tempStart; i<tempEnd; i++) {
    sb.AppendFormat(fmt, i);
    fmt=" UNION ALL SELECT {0},@A{0}";
    updateCommand.Parameters.AddWithValue("@A"+i.ToString(), Request.Form[i.ToString()]);
  }
  sb.Append(") x ON s.QuestionNum=x.q AND StudentID=@ID");
  updateCommand.CommandText = sb.ToString();
  updateCommand.Parameters.AddWithValue("@ID", uid);
  updateCommand.ExecuteNonQuery();
}
使用(SqlCommand updateCommand=newsqlcommand()){
updateCommand.CommandType=CommandType.Text;
updateCommand.Connection=conn;
如果(cn.State!=ConnectionState.Open)连接打开();
StringBuilder sb=new StringBuilder(“更新s集合答案=a FROM dbo.STUDENTAnswers JOIN(”);
string fmt=“选择{0}作为q,@A{0}作为A”;

对于(inti=tempStart;i我看到的一个问题是当您打开连接时

我至少会在每次更新之前调用open,然后在更新之后关闭连接

如果您的循环需要时间来执行,那么您的连接将被打开很长一段时间

除非需要,否则最好不要打开命令。

您可以使用批量插入。创建一个包含所有问题和答案的xml文档,并使用该文档插入值


编辑:如果您坚持使用当前的解决方案,我至少会将您的SqlConnection和SqlCommand包装在一个using块中,以确保它们得到处理。

对于30个更新,我认为您的思路是正确的,尽管关于需要using around
UPDATECOMAND
的评论是正确的


我们发现,执行批量更新(>100行)的最佳方式是通过
SqlBulkCopy
类对临时表进行批量更新,然后调用存储过程来填充活动表。

有几件事比较突出:

  • 您没有显示SqlConnection的实例化位置,因此不清楚您是否正确地处理了它

  • 您不应该在循环中吞咽异常-最好在顶级异常处理程序中处理它们

  • 在循环的每次迭代中,您都会实例化新的参数——您可以重用这些参数

把这些放在一起,它可能看起来像下面这样(如果您不想使用事务,即不关心某些但不是所有更新是否成功):

使用(SqlConnection conn=newsqlconnection(connectionString))
{
conn.Open();
使用(SqlCommand updateCommand=newsqlcommand(update,conn))
{
字符串uid=Session[“uid”].ToString();
updateCommand.Parameters.AddWithValue(“@ID”,uid);
updateCommand.Parameters.AddWithValue(“@qnum”,i);
updateCommand.Parameters.Add(“@answer”,System.Data.SqlDbType.VarChar);

对于(int i=tempStart;每次回发我循环运行大约30次。我的想法是我会保存打开和关闭30次。我错了吗?我同意,我宁愿有一个打开的连接,不管循环需要执行多长时间,也不愿打开和关闭连接N次。我认为是否处理循环中的异常应该取决于业务规则。dealing with exceptions out the loop意味着您要么停止处理出现错误的项目,要么回滚事务,但在某些情况下,您可能希望跳过错误行并继续处理。如果您希望跳过错误行并继续处理其他行,则您可能希望捕获SqlException并检查事务某些特定错误的SqlErrors属性。
using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();
    using (SqlCommand updateCommand = new SqlCommand(update, conn))
    {
        string uid = Session["uid"].ToString();
        updateCommand.Parameters.AddWithValue("@ID", uid);
        updateCommand.Parameters.AddWithValue("@qnum", i);
        updateCommand.Parameters.Add("@answer", System.Data.SqlDbType.VarChar);
        for (int i = tempStart; i <= tempEnd; i++)
        {
            updateCommand.Parameters["@answer"] = Request.Form[i.ToString()];
            updateCommand.ExecuteNonQuery();
        }
    }
}
using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();
    using (SqlTransaction transaction = conn.BeginTransaction())
    {
        using (SqlCommand updateCommand = new SqlCommand(update, conn, transaction))
        {
            string uid = Session["uid"].ToString();
            updateCommand.Parameters.AddWithValue("@ID", uid);
            updateCommand.Parameters.AddWithValue("@qnum", i);
            updateCommand.Parameters.Add("@answer", System.Data.SqlDbType.VarChar);
            for (int i = tempStart; i <= tempEnd; i++)
            {
                updateCommand.Parameters["@answer"] = Request.Form[i.ToString()];
                updateCommand.ExecuteNonQuery();
            }
            transaction.Commit();
        }
    } // Transaction will be disposed and rolled back here if an exception is thrown
}