2012-02-24 6 views
1

ストアドプロシージャを使用してSQL Serverデータベースに挿入するレコードのリストがあります。現在、私はこのようにしていますが、よりよい方法はありますか?ストアドプロシージャを使用してデータベースにリストレコードを挿入する

私はアプリのピーク時に100〜200行/秒を挿入しています。ストアドプロシージャは、値のみを取得していないと、新しい行あなたができる

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; 
        } 
       } 
      } 
     } 
    } 
+0

は、あなたがより良いパフォーマンス、コードの改善、のいずれかまたはをお探しですか? – Dan

+0

もし可能であれば、私は非常に新しいC言語で書かれていますが、私たちは200のレコードを持っていて、DB接続を200回開いていて、それを閉じて、いくつかの良いコーディングがありますか?メモリの改善または永続性のために – kawafan

+0

使用しているSql Serverのバージョンはどれですか? –

答えて

7

これはまさにテーブル値のパラメータです。あなたのリストをワンショットで渡すことができます。 SQL Serverで

C#で今すぐ
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 

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(); 
} 
+0

私は複数回投票したいです!!! – Steve

+0

これは優れたアイデアです。パフォーマンスも向上しますか? – kawafan

+0

絶対に。データベースとの接続を1つだけ行い、プロシージャを1回呼び出し、データを1つのストリームとして送信しています。 –

0

1つの明らかなものを挿入:メソッドの開始時に作成SqlCommand一度だけを - 何のポイントを経由し、何度も、それを作成するには再び!

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; 
       } 
      } 
     } 
    } 
+0

接続を200回開いても何か問題はありませんか? 1秒で?これはWebサービスのように継続的に発生します – kawafan

+0

@ user353600:ADO.NET接続はプールされているため、「開く」と「閉じる」は実際には大きな操作ではありません。しかし、はい - あなたはまた、 'foreach'の前に接続を開こうとするかもしれません - ちょうど例外の場合にエラー処理をちょっと複雑にします.... –