2012-09-10 4 views
0

목록의 값을 데이터 테이블로 전달한 다음 저장 프로 시저에 테이블 변수로 전달합니다. 어떤 이유로 인해 값이 Table 변수에서 올바르게 전달되지 않습니다. 나는 SQL 프로파일 러를 실행하고 모든 값이 데이터 테이블을 만들기 불필요한 오버 헤드가 NULL테이블 변수로 datatable을 저장 프로 시저에 전달할 수 없습니다.

 DataTable dbRk1 = new DataTable("dbRk1"); 
     dbRk1.Columns.Add("val1", typeof(String)); 
     dbRk1.Columns.Add("val2", typeof(DateTime)); 
     dbRk1.Columns.Add("val2", typeof(Int64)); 
     dbRk1.Columns.Add("val3", typeof(Int32)); 
     dbRk1.Columns.Add("val4", typeof(Int64)); 
     dbRk1.Columns.Add("val5", typeof(Int32)); 
     dbRk1.Columns.Add("val5", typeof(DateTime)); 

     drk.x.ForEach(x => dbRk1.Rows.Add(x)); 
     DataTable table = new DataTable(); 
     SqlConnection conn = null; 
     using (conn =new connection...) 
     { 
      SqlCommand cmd = new SqlCommand("[proc]", conn); 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.AddWithValue("@TableVariable", dbRk1); 
    cmd.ExecuteNonQuery(); 

}

 Alter PROCEDURE [dbo].[proc] 
    (
     @TableVar [dbo].[TableVar] READONLY 
    ) 
    AS 
BEGIN 
Set nocount on 
Declare @MYID INT 
Declare @SOMEDate DateTime 
Declare @NEWDate Date 


select @MYID = some_id, 
@SOMEDate = convert(date, db_some_date) from tbl_some 
where someval = (select tb.val1 from @TableVar as tb); 


Merge DeviceBillCycle as target 
    using (Select x.val1, x.val2, x.val3,x.val4, 
         x.val5,x.val6, x.val7 from @TableVar as x) 
    as Source 

    on val_id = @MYID 
    when matched and @MYID !=NULL then 

update set  val1= Source.[val1], 
        val2=Source.[val2], 
        val3=Source.[val3], 
        val4=Source.[val4], 
        val5=Source.[val5], 
        val6=Source.[val6] 

    when not matched and @MYID !=NULL then 
    insert 
    values (Source.[val1], 
      Source.[val2], 
      Source.[val3], 
       Source.[val4], 
       Source.[val5], 
       Source.[val6], 
       Source.[val7], 
       @MYID 
    )  ; 
end 
+0

drk.x.ForEach 후 (X => dbRk1.Rows.Add (X)); dbRk1의 몇 가지 값을 디버그하여 확인하십시오. 그리고 datatable을 사용하지 않는 곳에 답을 게시 할 것입니다. – Paparazzi

+0

네 말이 맞아. 값은 drk.x.ForEach (x => dbRk1.Rows.Add (x)); 동안 진행되지 않습니다. – user1110790

답변

1

로 오는 것을 발견했다.

목록이있는 경우 IEnumerable <SqlDataRecord>을 구현하여 직접 사용할 수 있습니다.
IEnumerable.GetEnumerator()에서 항상 PK로 정렬하여 인덱스 조각을 계속 유지합니다.
비동기가 생성되는 이유는 lastDocFTSinX를 만드는 것이 비용이 많이 들고 삽입 시간만큼 오래 걸립니다.

저는 IEnumerable <SqlDataRecord에서 디버그 할 수 있습니다.

SqlConnection sqlConnFTSindexInX = new SqlConnection(builder.ToString()); 
sqlConnFTSindexInX.Open(); 
SqlCommand sqlCmdFTSindexInX = new SqlCommand("InsertFTSindexInXTablock_TVP", sqlConnFTSindexInX); 
sqlCmdFTSindexInX.CommandType = CommandType.StoredProcedure; 
AsyncCallback callbackFTSindexInX = new AsyncCallback(HandleCallbackFTSindexInX); 
SqlParameter tvpParamFTSindexInX = sqlCmdFTSindexInX.Parameters.Add("@ItemTVP", SqlDbType.Structured); 
tvpParamFTSindexInX.Direction = ParameterDirection.Input; 

다음 그룹 루프에

while (isExecutingFTSindexInX) 
{ 
    Thread.Sleep(10); 
}  
docFTSinXsCollection = new DocFTSinXsCollection(lastSID, lastDocFTSinX); 
tvpParamFTSindexInX.Value = docFTSinXsCollection; 
sqlCmdFTSindexInX.BeginExecuteNonQuery(callbackFTSindexInX, sqlCmdFTSindexInX); 
// the callback will set isExecutingFTSindexInX = false; 


    public class DocFTSinXsCollection : List<DocFTSinX>, IEnumerable<SqlDataRecord> 
    { 
     // used by TVP for fast insert 
     private int sID; 
     private IEnumerable<DocFTSinX> docFTSinXs; 
     IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator() 
     { 
      var sdr = new SqlDataRecord(
      new SqlMetaData("wordID1", System.Data.SqlDbType.Int), 
      new SqlMetaData("wordID2", System.Data.SqlDbType.Int), 
      new SqlMetaData("sID", System.Data.SqlDbType.Int), 
      new SqlMetaData("Delta", System.Data.SqlDbType.Int)); 
      foreach (DocFTSinX oh in docFTSinXs.OrderBy(x => x.Word1).ThenBy(x => x.Word2)) 
      { 
       sdr.SetInt32(0, oh.Word1); 
       sdr.SetInt32(1, oh.Word2); 
       sdr.SetInt32(2, sID); 
       sdr.SetInt32(3, (Int32)oh.Delta); 
       yield return sdr; 
      } 
     } 

     public DocFTSinXsCollection(int SID, IEnumerable<DocFTSinX> DocFTSinXs) 
     { 
      sID = SID; 
      docFTSinXs = DocFTSinXs; 
      //Debug.WriteLine("DocFTSinXsCollection DocFTSinXs " + DocFTSinXs.Count().ToString()); 
     } 
    } 
+0

감사합니다. @Blam. docFTSinXsCollection = new DocFTSinXsCollection (lastSID, lastDocFTSinX)을 사용하는 방법에 대해 설명해주십시오. 테이블 변수에 ID 필드가 없습니다. 또한 내 메서드가 데이터 테이블에 값을로드하지 않는 이유를 알고 있습니까? 정말 고마워요. – user1110790

+0

ID가 없도록 생성자를 수정하십시오. DataTable에 행이 없으면 drk.x.ForEach (x => dbRk1.Rows.Add (x))를 수정해야합니다. DataTable에 행을 추가하는 구문은 간결하지 않습니다. – Paparazzi

+0

@Blam .i 감사합니다. 내 foreach 루프를 아래와 같이 수정했습니다. foreach (var someRecord in someReport) { var dr = someReport.NewRow(); dr [ "val1"] = someRecord.val1; ....... datatable.Rows.Add (dr); } – user1110790

관련 문제