我是ado.net的新手,目前正在将数据表记录插入我的数据库表。
我有一个包含一些数据的Excel文件,我在这个Excel文件中创建一个包含大量数据表的数据集。
在这个数据集中,我有两个数据表形式:
带有记录的数据表0:类别
ParentCategory Description
Electronics jhdkhsd
Sports kjshfhs
带有记录的数据表1:子类别
Subcategory ParentCategory Description
Mobile Electronics weprwp
Tv Electronics sdflskd
Balls Sports kjshdfkjh
Shoes Sports uytuyt
现在我的数据库表是这样的:
Category:Id,Name,parentid
所以基本上我试图在我的数据库表中插入所有这些数据表数据,这些数据是类数据表和SubCategory数据表,但是当我试图插入获取错误时:
错误:参数化查询'(@Id int output,@ ParentCategory nvarchar(50))插入Category'期望参数 '@ ParentCategory',未提供。
到目前为止,这是我的代码:
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]);
}
这里我添加了所有类别数据表行rowstate state属性,所以我直接尝试插入所有类别记录。
我是否必须循环到单个记录并插入?由于我拥有数千个类别及其子类别,并且这样做会使我的系统变慢。
答案 0 :(得分:1)
使用以下代码段。
使用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]);
}
以上内容应该注意您在帖子中提到的错误消息。
下面的代码片段将帮助您批量插入行,而不是一次需要在数据库中插入许多行时插入行。对于批处理插入语句,您需要将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]);
}
在进行批量插入时,需要记住几点。
从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();
}
}