C#批量插入数据库
C# bulk insert to database
我有 winform 从 comboBox
获取 id
并从 listBox
获取多个值然后我需要存储这个 listBox
项目和我的 comboBox
项。
**当前行为`
如果我的 listBox
中只有一项,它会存储。但如果有多个项目(这是使用 listBox
的目的),它 return 会出现以下错误:
Message: Procedure or function InsertSerial has too many arguments specified.
预期行为
获取listBox
中的所有项目并将它们一起添加到数据库(批量插入)
代码
Table schema
CREATE TABLE [dbo].[Serials] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[ProductId] INT NOT NULL,
[Serial] VARCHAR (50) NOT NULL,
[Sold] BIT DEFAULT ((0)) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_Serials_Products] FOREIGN KEY ([ProductId]) REFERENCES [dbo].[Products] ([Id])
);
StoredProcedur
CREATE PROCEDURE [dbo].[InsertSerial]
@ProductId INT,
@Serial NVARCHAR(50),
@Sold INT
AS
begin
INSERT into Serials(ProductId, Serial, Sold) values (@ProductId,@Serial,@Sold);
end
form
// save button
private void snStoreBtn_Click(object sender, EventArgs e)
{
try
{
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyApp.Properties.Settings.MyAppDatabaseString"].ConnectionString))
{
if (cn.State == ConnectionState.Closed)
cn.Open();
using (SqlCommand cmd = new SqlCommand("dbo.InsertSerial", cn))
{
foreach (var item in listBox1.Items)
{
Console.WriteLine("Item::: {0}", item.ToString());
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@ProductId", selectedProductId);
cmd.Parameters.AddWithValue("@Serial", item.ToString()); //Message: Procedure or function InsertSerial has too many arguments specified.
cmd.Parameters.AddWithValue("@Sold", "0");
cmd.ExecuteNonQuery();
}
cn.Close();
}
backgroundWorker1.RunWorkerAsync();
progressBarStoringData.Visible = true;
progressLabel.Visible = true;
}
// clear the listBox
listBox1.Items.Clear();
}
catch (SqlException ex)
{
StringBuilder errorMessages = new StringBuilder();
for (int i = 0; i < ex.Errors.Count; i++)
{
errorMessages.Append("Index #" + i + "\n" +
"Message: " + ex.Errors[i].Message + "\n" +
"LineNumber: " + ex.Errors[i].LineNumber + "\n" +
"Source: " + ex.Errors[i].Source + "\n" +
"Procedure: " + ex.Errors[i].Procedure + "\n");
}
Console.WriteLine(errorMessages.ToString());
}
}
问题
我应该如何正确循环我的 listBox
项目才能正确存储在数据库中?
将 using (SqlCommand cmd = new SqlCommand("dbo.InsertSerial", cn)) 放入循环中,这样每次都创建一个新命令,否则每次都会向同一命令添加更多参数时间.
只需添加一次参数,每次执行只需更改它们的值。
using (SqlCommand cmd = new SqlCommand("dbo.InsertSerial", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
var pProductId = cmd.Parameters.Add("@ProductId", SqlDbType.Int);
var pSerial = cmd.Parameters.AddWithValue("@Serial",
SqlDbType.VarChar);
pSerial.Size=50;
var pSold = cmd.Parameters.AddWithValue("@Sold", SqlDbType.Int);
foreach (var item in listBox1.Items)
{
pProductId.Value = selectedProductId;
pSerial.Value = item.ToString();
pSold.Value = 0;
Console.WriteLine("Item::: {0}", item.ToString());
cmd.ExecuteNonQuery();
}
cn.Close();
}
我有 winform 从 comboBox
获取 id
并从 listBox
获取多个值然后我需要存储这个 listBox
项目和我的 comboBox
项。
**当前行为`
如果我的 listBox
中只有一项,它会存储。但如果有多个项目(这是使用 listBox
的目的),它 return 会出现以下错误:
Message: Procedure or function InsertSerial has too many arguments specified.
预期行为
获取listBox
中的所有项目并将它们一起添加到数据库(批量插入)
代码
Table schema
CREATE TABLE [dbo].[Serials] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[ProductId] INT NOT NULL,
[Serial] VARCHAR (50) NOT NULL,
[Sold] BIT DEFAULT ((0)) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_Serials_Products] FOREIGN KEY ([ProductId]) REFERENCES [dbo].[Products] ([Id])
);
StoredProcedur
CREATE PROCEDURE [dbo].[InsertSerial]
@ProductId INT,
@Serial NVARCHAR(50),
@Sold INT
AS
begin
INSERT into Serials(ProductId, Serial, Sold) values (@ProductId,@Serial,@Sold);
end
form
// save button
private void snStoreBtn_Click(object sender, EventArgs e)
{
try
{
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyApp.Properties.Settings.MyAppDatabaseString"].ConnectionString))
{
if (cn.State == ConnectionState.Closed)
cn.Open();
using (SqlCommand cmd = new SqlCommand("dbo.InsertSerial", cn))
{
foreach (var item in listBox1.Items)
{
Console.WriteLine("Item::: {0}", item.ToString());
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@ProductId", selectedProductId);
cmd.Parameters.AddWithValue("@Serial", item.ToString()); //Message: Procedure or function InsertSerial has too many arguments specified.
cmd.Parameters.AddWithValue("@Sold", "0");
cmd.ExecuteNonQuery();
}
cn.Close();
}
backgroundWorker1.RunWorkerAsync();
progressBarStoringData.Visible = true;
progressLabel.Visible = true;
}
// clear the listBox
listBox1.Items.Clear();
}
catch (SqlException ex)
{
StringBuilder errorMessages = new StringBuilder();
for (int i = 0; i < ex.Errors.Count; i++)
{
errorMessages.Append("Index #" + i + "\n" +
"Message: " + ex.Errors[i].Message + "\n" +
"LineNumber: " + ex.Errors[i].LineNumber + "\n" +
"Source: " + ex.Errors[i].Source + "\n" +
"Procedure: " + ex.Errors[i].Procedure + "\n");
}
Console.WriteLine(errorMessages.ToString());
}
}
问题
我应该如何正确循环我的 listBox
项目才能正确存储在数据库中?
将 using (SqlCommand cmd = new SqlCommand("dbo.InsertSerial", cn)) 放入循环中,这样每次都创建一个新命令,否则每次都会向同一命令添加更多参数时间.
只需添加一次参数,每次执行只需更改它们的值。
using (SqlCommand cmd = new SqlCommand("dbo.InsertSerial", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
var pProductId = cmd.Parameters.Add("@ProductId", SqlDbType.Int);
var pSerial = cmd.Parameters.AddWithValue("@Serial",
SqlDbType.VarChar);
pSerial.Size=50;
var pSold = cmd.Parameters.AddWithValue("@Sold", SqlDbType.Int);
foreach (var item in listBox1.Items)
{
pProductId.Value = selectedProductId;
pSerial.Value = item.ToString();
pSold.Value = 0;
Console.WriteLine("Item::: {0}", item.ToString());
cmd.ExecuteNonQuery();
}
cn.Close();
}