无法将datatable作为表变量传递给存储过程

时间:2012-09-10 19:34:41

标签: .net sql-server-2008 c#-4.0 stored-procedures datatable

我将值从列表传递到数据表,然后将数据表作为表变量传递给存储过程。由于某种原因,值未在Table变量中正确传递。 我运行了sql profiler,发现所有的值都是NULL

        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 

1 个答案:

答案 0 :(得分:1)

创建数据表是不必要的开销。

如果您有列表,可以通过实施IEnumerable <SqlDataRecord&gt;直接使用它 我总是按照IEnumerable.GetEnumerator()中的PK排序,以保持索引碎片化。
asynch创建lastDocFTSinX的原因很昂贵,并且需要与插入一样长。

我喜欢你可以在IEnumerable <SqlDataRecord&gt;中调试。

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