在我的数据库 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]);
}
进行批量插入时,需要牢记几点。
- 插入命令的 CommandTimeout 应该足够大以允许批量插入 否则您将以超时异常结束。如果将此超时设置为 0,则允许插入的时间是不确定的。
- 进行批量插入时,您希望获得最佳性能,否则您的插入最终可能会太慢。通过将批量插入作为单个事务执行,您将获得这种提高的性能。如果没有事务,数据库将为批处理中的每个 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();
}
}
我是 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]);
}
进行批量插入时,需要牢记几点。
- 插入命令的 CommandTimeout 应该足够大以允许批量插入 否则您将以超时异常结束。如果将此超时设置为 0,则允许插入的时间是不确定的。
- 进行批量插入时,您希望获得最佳性能,否则您的插入最终可能会太慢。通过将批量插入作为单个事务执行,您将获得这种提高的性能。如果没有事务,数据库将为批处理中的每个 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();
}
}