Inserting list records in database with stored procedures
-
12-11-2019 - |
Question
I have a list of records inserting into a SQL Server database using a stored procedure. Currently I am doing it this way but is there any better way?
I am inserting 100-200 rows per/sec on peak hours of my app. The stored procedure only gets the values and inserts the new row
public void InsertRecords(List<stRecord> records)
{
foreach (var item in records)
{
if (CheckforDuplicateRecord(item) == false)
{
using (con = new SqlConnection(connectionString))
{
con.Open();
SqlCommand cmd = new SqlCommand(StoredProcedures.Service_Insert_record.ToString(), con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@item1", SqlDbType.NChar);
cmd.Parameters.Add("@item2", SqlDbType.NChar);
cmd.Parameters[0].Value = item.localUsername;
cmd.Parameters[1].Value = item.BetfairUsername;
try
{
cmd.ExecuteNonQuery();
}
catch (Exception exp)
{
throw exp;
}
}
}
}
}
Solution
This is exactly what table-valued parameters are for - you can pass your list in one shot.
In SQL Server:
CREATE TYPE dbo.Usernames AS TABLE
(
localUsername NVARCHAR(32),
BetfairUsername NVARCHAR(32)
);
GO
CREATE PROCEDURE dbo.Service_Insert_MultipleRows
@u AS dbo.Usernames READONLY
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.DestinationTable(localUsername, BetfairUsername)
SELECT localUsername, BetfairUsername FROM @u;
END
GO
Now in C#:
DataTable tvp = new DataTable();
tvp.Columns.Add(new DataColumn("localUsername"));
tvp.Columns.Add(new DataColumn("BetfairUsername"));
foreach(var item in records)
{
tvp.Rows.Add(item.localUsername, item.BetfairUsername);
}
using (con)
{
SqlCommand cmd = new SqlCommand("Service_Insert_MultipleRows", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter tvparam = cmd.Parameters.AddWithValue("@u", tvp);
tvparam.SqlDbType = SqlDbType.Structured;
con.Open();
cmd.ExecuteNonQuery();
}
OTHER TIPS
One obvious thing you could do: create the SqlCommand
only once at the beginning of the method - no point in creating it over and over and over again!
public void InsertRecords(List<stRecord> records)
{
using (con = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(StoredProcedures.Service_Insert_record.ToString(), con))
{
cmd.CommandType = CommandType.StoredProcedure;
// are those paramters *REALLY* just 1 character long??
// that's what you have now, with the way you define it!
cmd.Parameters.Add("@item1", SqlDbType.NChar);
cmd.Parameters.Add("@item2", SqlDbType.NChar);
// otherwise, you need to define the LENGTH of the NCHAR parameter!
// cmd.Parameters.Add("@item2", SqlDbType.NChar, 15);
foreach (var item in records)
{
if (CheckforDuplicateRecord(item) == false)
{
cmd.Parameters["@item1"].Value = item.localUsername;
cmd.Parameters["@item2"].Value = item.BetfairUsername;
try
{
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception exp)
{
throw;
}
}
}
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow