在我的数据库 table 中插入数据 tables 记录时出错

Getting error while inserting datatables records in my database table

我是 ado.net 的新手,目前正在将数据 table 记录插入我的数据库 tables。

我有 1 个 Excel 文件,其中包含一些数据,我正在从这个 Excel 文件创建一个包含大量数据的数据集table。

在这个数据集中,我有 2 个数据table,形式如下:

数据table 0 条记录:类别

ParentCategory Description
  Electronics   jhdkhsd
  Sports        kjshfhs

数据table 1 条记录:SubCategory

Subcategory ParentCategory  Description
  Mobile       Electronics   weprwp
  Tv           Electronics   sdflskd
  Balls        Sports        kjshdfkjh
  Shoes        Sports        uytuyt

现在我的数据库 tables 是这样的:

Category:Id,Name,parentid

所以基本上我试图在我的数据库 table 中插入所有这些数据 table 类别数据 table 和子类别数据 table但是当我尝试插入时出现错误:

Error:The parameterized query '(@Id int output,@ParentCategory nvarchar(50))insert into Category' expects the parameter '@ParentCategory', which was not supplied.

到目前为止,这是我的代码:

 var dsFinal = new DataSet();

    //Some code to read Excel sheets and data from Excel and create datatables and records with it.


    //code to insert records
     using (SqlConnection connection = new SqlConnection(""))
     {
       SqlDataAdapter adapter = new SqlDataAdapter();
       var insertCommand = new SqlCommand("insert into Category (Name) values (@ParentCategory) SET @Id = SCOPE_IDENTITY()", connection);
      var parameter = insertCommand.Parameters.Add("@Id", SqlDbType.Int, 0, "Id");
      insertCommand.Parameters.Add("@ParentCategory", SqlDbType.NVarChar, 50, "Name");
      parameter.Direction = ParameterDirection.Output;
     insertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
     adapter.InsertCommand = insertCommand;
    adapter.Update(dsFinal .Tables[0]);
   }

这里我添加了所有类别数据table 行 rowstate 状态 属性 所以我直接尝试插入所有类别记录。

我是否必须循环到单个记录并插入?因为我有数以千计的类别及其子类别,所以这样做会降低我的系统速度。

使用以下代码片段。

  • 您需要在 SQL for insert 命令中的 INSETRT 和 SCOPE_IDENTITY 语句之间指定一个分号。
  • 此外,由于您的基础 table 包含 ID、Name、ParentId 列,因此您必须将所有这些列映射到您的插入命令,并且仅插入 Name 和 ParentId 列,因为 ID 是自动生成的。 ID 列映射到输出参数,而其他列映射到输入参数。

使用 DataTable 将单行插入数据库

     using(SqlConnection connection = new SqlConnection("")) {
      SqlDataAdapter adapter = new SqlDataAdapter();
      var insertCommand = new SqlCommand("Insert into Category (Name, ParentId) Values (@name, @parentId); SET @ID = SCOPE_IDENTITY(); ", connection);
      var parameter = insertCommand.Parameters.Add("@name", SqlDbType.NVarChar, 50, "Name");
      insertCommand.Parameters.Add("@parentId", SqlDbType.Int, 0, "ParentId");
      SqlParameter parameter = adapter.InsertCommand.Parameters.Add("@ID",SqlDbType.Int, 0, "ID");
      parameter.Direction = ParameterDirection.Output;
      adapter.insertCommand = insertCommand;
      adapter.insertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
      adapter.Update(dsControlSheet.Tables[0]);
    }

以上内容应该处理您在 post.

中提到的错误消息

下面的代码片段将帮助您批量插入行,而不是在需要向数据库中插入多行时一次插入一行。对于批处理插入语句,您需要将 adpapter.UpdateBatchSize 指定为大于 1 的值。

从DataTable批量插入行到数据库

 using (SqlConnection connection = new SqlConnection(""))
 {
   SqlDataAdapter adapter = new SqlDataAdapter();
   var insertCommand = new SqlCommand("Insert into Category (Name, ParentId) Values (@name, @parentId);", connection);
   var parameter = insertCommand.Parameters.Add("@name", SqlDbType.NVarChar, 50, "Name");
   insertCommand.Parameters.Add("@parentId", SqlDbType.Int, 0, "ParentId");
   adapter.insertCommand = insertCommand;
   // When setting UpdateBatchSize to a value other than 1, all the commands 
   // associated with the SqlDataAdapter have to have their UpdatedRowSource 
   // property set to None or OutputParameters. An exception is thrown otherwise.
     insertCommand.UpdatedRowSource = UpdateRowSource.None;
   // Gets or sets the number of rows that are processed in each round-trip to the server.
   // Setting it to 1 disables batch updates, as rows are sent one at a time.
    adapter.UpdateBatchSize = 50;
    adapter.Update(dsControlSheet.Tables[0]);
}

进行批量插入时,需要牢记几点。

  1. 插入命令的 CommandTimeout 应该足够大以允许批量插入 否则您将以超时异常结束。如果将此超时设置为 0,则允许插入的时间是不确定的。
  2. 进行批量插入时,您希望获得最佳性能,否则您的插入最终可能会太慢。通过将批量插入作为单个事务执行,您将获得这种提高的性能。如果没有事务,数据库将为批处理中的每个 INSERT 启动一个事务,这将花费更多时间。例如,如果批量大小为 500(即 adapter.UpdateBatchSize),如果插入命令没有附加任何事务,那么 500 个 INSERT 语句将在数据库中产生 500 个事务;但是如果您将事务附加到插入命令,那么所有 500 个 INSERT 将只有 1 个事务,这会使性能提高。

从 DataTable 批量插入数据库的高性能

 using (SqlConnection connection = new SqlConnection(connectionString))
 {
   SqlDataAdapter adapter = new SqlDataAdapter();
   var insertCommand = new SqlCommand("Insert into Category (Name, ParentId) Values (@name, @parentId);", connection);
   var parameter = insertCommand.Parameters.Add("@name", SqlDbType.NVarChar, 50, "Name");
   insertCommand.Parameters.Add("@parentId", SqlDbType.Int, 0, "ParentId");
   adapter.insertCommand = insertCommand;
   // When setting UpdateBatchSize to a value other than 1, all the commands 
   // associated with the SqlDataAdapter have to have their UpdatedRowSource 
   // property set to None or OutputParameters. An exception is thrown otherwise.
     insertCommand.UpdatedRowSource = UpdateRowSource.None;
   // Gets or sets the number of rows that are processed in each round-trip to the server.
   // Setting it to 1 disables batch updates, as rows are sent one at a time.
    adapter.UpdateBatchSize = 50;
    //NOTE: When doing batch updates it's a good idea to fine tune CommandTimeout value
    //since default is 30 seconds. If your batch insert takes more than 30 s (default value)
    //then make sure to increase this value. I am setting this to 90 s
    //but you must decide this based on your situation.
    //Set this to 0 if you are not sure how long your batch inserts will take
    insertCommand.CommandTimeout = 90;

    //HOW TO MAKE BATCH INSERTS FASTER IN PERFORMANCE
    //Perform batch updates in a single transaction to increase batch insert performance
    connection.Open();
    var transaction = connection.BeginTransaction();
    insertCommand.Transaction = transaction;
    try { 
         adapter.Update(dsControlSheet.Tables[0]);
         transaction.Commit();
    }
    catch(Exception e) {

    if(transaction!=null) {
       transaction.Rollback();
     }
     //log exception
   }
   finally {
      connection.Close();
   }
}