【问题标题】:ExecuteNonQuery() breaks the loop and doesn't insert data in SQL databaseExecuteNonQuery() 打破循环并且不在 SQL 数据库中插入数据
【发布时间】:2015-08-28 16:42:13
【问题描述】:

这是尝试输入存储在数组中的数据的代码。数组包含数据以及不需要添加到数据库中的空单元格。问题是代码没有抛出任何异常或错误,但也没有在数据库中插入任何数据!请帮助...在此先感谢

public void saveDb(string[,] timeTableId,string[,] start_time,string[,] end_time,string[,] subject_id,string[,] day,string[,] faculty_id)
{
    SqlConnection con;
    SqlCommand cmd;
    con = new SqlConnection("Data Source=.;Initial Catalog=AIS;Integrated Security=True");
    con.Open();
    for (int i = 0; i < 8; i++)
    {
        for (int j = 1; j <= 7; j++)
        {
            if (subject_id[i, j].Length != 0 && subject_id[i, j] != null)
            {
                cmd = new SqlCommand("INSERT INTO TIMETABLE VALUES('" + subject_id[i, j] + "','" + day[i, j] + "','" + start_time[i, j] + "','" + end_time[i, j] + "','" + subject_id[i, j] + "','" + faculty_id[i, j] + "')", con);
                cmd.ExecuteNonQuery();
            }
            else
            { 
            }
        }
    }
    con.Close();
}

【问题讨论】:

  • SQL Injection alert - 您应该将您的 SQL 语句连接在一起 - 使用 参数化查询 来避免 SQL 注入
  • @marc_s 你能详细说明一下吗?
  • 阅读他在评论中的链接,它解释了。
  • 如果我尝试创建一个名为:');DROP Table Timetable; 的主题怎么办?
  • 或者如果这些字段中的任何一个实际上有一个单引号作为其中的有效数据片段怎么办?撇号并不罕见。

标签: asp.net sql-server executenonquery


【解决方案1】:

好的,我正在详细说明....

  1. 使用 参数化 查询 - 首先是为了避免 SQL 注入,这是 Internet 上排名第一的漏洞,其次是为了避免 我需要多少单引号或双引号的问题对于这个字符串或日期? 和类似的东西 - 如果你使用正确类型的参数就消失了,第三个是为了提高性能 - 定义你的参数一次,重复使用它们多次(和 SQL服务器还将创建一个带有执行计划的 SQL 语句并重用它!)

  2. 对所有一次性类使用 **using(....) { .... } 块 - 尤其是 SqlConnectionSqlCommandSqlDataReader - 以确保正确和立即处理不需要的对象。

  3. 总是明确定义要插入的表的列列表 - 不要只依赖当前表结构和列顺序 - 明确地说 你在做什么!

总而言之,你的方法应该看起来像这样:

public void saveDb(string[,] timeTableId,string[,] start_time,string[,] end_time,string[,] subject_id,string[,] day,string[,] faculty_id)
{
    // define connection string - typically should come from a .config file
    string connectionString = "Data Source=.;Initial Catalog=AIS;Integrated Security=True";

    // define the SQL query - with *parameters* - and also: explicitly NAME the columns in your target table!
    // also: did you really want to insert the subject_id twice?
    string insertQry = "INSERT INTO dbo.TIMETABLE (col1, col2, col3, ....) " + 
                       " VALUES(@subject_id, @day, @start_time, @end_time, @subject_id, @faculty_id)";

    // set up your connection and command    
    // you didn't tell us what datatypes those are - maybe you need to adapt those to your situation!
    using (SqlConnection con = new SqlConnection(connectionString))
    using (SqlCommand cmd = new SqlCommand(insertQry, con))
    {
        // define your parameters once, before the loop
        cmd.Parameters.Add("@subject_id", SqlDbType.Int);
        cmd.Parameters.Add("@day", SqlDbType.DateTime);
        cmd.Parameters.Add("@start_time", SqlDbType.Time);
        cmd.Parameters.Add("@end_time", SqlDbType.Time);
        cmd.Parameters.Add("@faculty_id", SqlDbType.Int);

        con.Open();

        // now start the for loops, and set the parameter values        
        for (int i = 0; i < 8; i++)
        {
            for (int j = 1; j <= 7; j++)
            {
                // not sure what these checks should be - left them "as is"
                if (subject_id[i, j].Length != 0 && subject_id[i, j] != null)
                {
                     // set the parameter values
                     cmd.Parameters["@subject_id"].Value = subject_id[i, j];
                     cmd.Parameters["@day"].Value = day[i, j];
                     cmd.Parameters["@start_time"].Value = start_time[i, j];
                     cmd.Parameters["@end_time"].Value = end_time[i, j];
                     cmd.Parameters["@faculty_id"].Value = faculty_id[i, j];

                     // execute query to insert data                     
                     cmd.ExecuteNonQuery();
                }    
            }
        }

        con.Close();
    }
}

【讨论】:

    【解决方案2】:

    尝试使用 SQL Profiler 捕获 SQL 语句,然后在 SQL Management Studio 上运行查询以发现它是否有任何错误。

    【讨论】:

      【解决方案3】:

      试试:

      使用parameterized查询并使用Try catch块获取exception如果有的话

      public void saveDb(string[,] timeTableId,string[,] start_time,string[,] end_time,string[,] subject_id,string[,] day,string[,] faculty_id)
      {
       SqlConnection con;
        SqlCommand cmd;
          con = new SqlConnection("Data Source=.;Initial Catalog=AIS;Integrated Security=True");
      try
      {
         if(con.State == ConnectionState.Closed)
                con.Open();
      
          for (int i = 0; i < 8; i++)
          {
              for (int j = 1; j <= 7; j++)
              {
                  if (subject_id[i, j].Length != 0 && subject_id[i, j] != null)
                  {
                      cmd = new SqlCommand("INSERT INTO [TIMETABLE](col1,col2,col3,col4,col5,col6) VALUES(@col1,@col2,@col3,@col4,@col5,@col6)", con);
      
      cmd.Parameter.AddWithValue("@col1",subject_id[i, j]);
         // convert type here depend upon the col type
          // cmd.Parameter.AddWithValue("@col1",Convert.ToString(subject_id[i, j]));
         //Or  cmd.Parameter.AddWithValue("@col1",Convert.ToDouble(subject_id[i, j]));
      cmd.Parameter.AddWithValue("@col2",day[i, j]);
      cmd.Parameter.AddWithValue("@col3",start_time[i, j]);
      cmd.Parameter.AddWithValue("@col4",end_time[i, j]);
      cmd.Parameter.AddWithValue("@col5",subject_id[i, j]);
      cmd.Parameter.AddWithValue("@col6",faculty_id[i, j]);
      
                      cmd.ExecuteNonQuery();
                  }
              }
          }
      }
      Catch(Exception e1)
      {
        throw new System.ArgumentException(e1.Messege, "Error");
      }
      Finally
      {
         if(con.State == ConnectionState.Open)
              con.Close();
      }
      }
      

      【讨论】:

      • 接球/投球让我很难过。 AddWithValue() 也是如此,这可能会导致严重的性能问题。
      • @JoelCoehoorn 谢谢你,你有什么建议来代替AddWithValue() ??
      • AddWithValue("@param", value) 将变为:Add("@param", SqlDbType.SomeType).Value = valueAdd("@param", SqlDbType.SomeType, lengthvariable).Value = value
      • @user3540365 你好,当我按照你所说的方式尝试时,我得到了以下异常:将 nvarchar 值“星期一”转换为数据类型 int 时转换失败。我不知道它为什么要尝试将其转换为 int ,如果是这样,为什么在从第一个数组插入时不会引起任何问题? 'Monday' 来自 day[i,j] 数组。提前致谢。
      • @user2895532 是的,就是这样,每个人都在问.. 现在,您需要根据您的要求进行适当的转换。如果day[i,j] Monday 则不能将其插入col2 int 列。
      猜你喜欢
      • 1970-01-01
      • 2019-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      相关资源
      最近更新 更多