插入数据时关闭阅读器时无效尝试调用读取

时间:2017-11-20 18:53:20

标签: c# sql sql-server wpf

我有一个按钮,当点击时将文本框和组合框字段中的数据插入到数据库表中,但每次插入它都会给我"当读取器关闭时无效尝试调用读取"。我怎样才能摆脱这个错误。关于优化代码的提示是受欢迎的,因为我知道我是一个完整的菜鸟。感谢

// AppServiceProvider
public function boot()
{
    Relation::morphMap([
        'posts' => Post::class,
        'posts' => ReadOnlyPost::class, <--- Can't do this

1 个答案:

答案 0 :(得分:2)

让我们尝试对您的代码进行一些调整。

  • 首先要考虑的是使用参数化查询而不是a 构建sql命令时的字符串连接。这是强制性的 避免解析错误和Sql Injections
  • 其次,您应该将一次性对象封装在using statement中 确保他们在你完成后得到适当的处理 使用它们。
  • 第三,您可以从表中获取LOCATION_ID而无需运行 单独查询只需将SELECT SCOPE_IDENTITY()作为第二批添加到第一个命令中。 (仅当您将第一个表中的LOCATION_ID字段声明为IDENTITY列时才有效)
  • 第四,你把所有东西放在transaction中,以避免出现问题 一些代码意外失败

所以:

SqlTransaction tr = null;
try
{
    string cmdText = @"insert into location(Storage, Shelf, columns, rows) 
                       values(@storage,@shelf,@columns,@rows);
                       select scope_identity()"; 
    using(SqlConnection sqlCon = new SqlConnection(.....))
    using(SqlCommand cmd = new SqlCommand(cmdText, sqlCon))
    {
         sqlCon.Open();
         using( tr = sqlCon.BeginTransaction())
         {
             // Prepare all the parameters required by the command
             cmd.Parameters.Add("@storage", SqlDbType.Int).Value = Convert.ToInt32(txtWarehouse.Text);
             cmd.Parameters.Add("@shelf", SqlDbType.Int).Value = Convert.ToInt32(txtShelf.Text);
             cmd.Parameters.Add("@columns", SqlDbType.Int).Value = Convert.ToInt32(txtColumn.Text );
             cmd.Parameters.Add("@rows", SqlDbType.Int).Value = Convert.ToInt32(txtRow.Text);

             // Execute the command and get back the result of SCOPE_IDENTITY
             int newLocation = Convert.ToInt32(cmd.ExecuteScalar());

             // Set the second command text
             cmdText = @"insert into product(SKU, nimetus, minimum, maximum, quantity,location_ID,category_ID,OrderMail_ID) 
                         values (@sku, @nimetus,@min,@max,@qty,@locid,@catid,@ordid)";

              // Build a new command with the second text
              using(SqlCommand cmd1 = new SqlCommand(cmdText, sqlCon))
              {
                  // Inform the new command we are inside a transaction
                  cmd1.Transaction = tr;

                  // Add all the required parameters for the second command
                  cmd1.Parameters.Add("@sku", SqlDbType.NVarChar).Value = txtSku.Text;
                  cmd1.Parameters.Add("@nimetus",SqlDbType.NVarChar).Value = txtNimetus.Text;
                  cmd1.Parameters.Add("@locid", SqlDbType.Int).Value = newLocation;
                  .... and so on for the other parameters required

                  cmd1.ExecuteNonQuery();
                  // If we reach this point the everything is allright and
                  // we can commit the two inserts together
                  tr.Commit();
             }
        }
    }
}
catch (Exception er)
{
    // In case of exceptions do not insert anything...
    if(tr != null) 
       tr.Rollback();
    MessageBox.Show(er.Message);
}

请注意,在第一个命令中,我使用了SqlDbType.Int类型的参数,因为您没有在文本周围使用单引号。这应该根据表列的实际数据类型进行验证,并进行调整以匹配类型。这对于第二个命令也是如此,其中您将所有内容都放在文本中,尽管其中一些字段似乎是整数(_location_id_可能是整数)。请核实你的桌子。