2012-02-24 3 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 서버에서

:

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

물론입니다. 데이터베이스에 정확히 하나의 연결을 만들고 프로 시저를 한 번 호출하고 데이터를 단일 스트림으로 보냅니다. –

0

하나 개 분명한 것은 삽입 : 방법의 시작 부분에 생성 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 초 만에? 이것은 웹 서비스이므로 계속 발생합니다. – kawafan

+0

@ user353600 : ADO.NET 연결이 풀링되므로 "열기"와 "닫기"는 전혀 큰 작업이 아닙니다. 하지만 네 - 또한 foreach 앞에 연결을 열려고 시도 할 수도 있습니다 - 그냥 예외가 더 복잡한 경우 에러 처리를합니다 .... –

관련 문제