2013-11-01 19 views
2

如果我有一個包含RowVersion列的SQLDataRecord,如下面的代碼所示。我總是得到一個SQL Server錯誤8052如何在調用存儲過程時在表值參數中包含RowVerson列?

傳入的表格數據流(TDS)遠程過程調用(RPC) 協議流不正確。表值參數%d(「%。* ls」),行 %I64d,列%d:數據類型0x%02X(用戶定義的表類型)時間戳 列需要爲缺省值。

是否將RowVersion值設置爲null或值。

我希望能夠爲現有記錄發送RowVersion值,並將ADO.NET中的新記錄發送到存儲過程,以便在合併記錄時使用optomistic併發檢查。

這怎麼辦?

namespace MyApplication.DataAccess 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Data; 
    using System.Linq; 
    using Microsoft.SqlServer.Server; 

    public interface IRowVersionRecord 
    { 
     Byte[] RowVersionValue { get; set; } 
     Int32? Somevalue { get; set; } 
    } 

    public class RowVersionRecordBase : IRowVersionRecord 
    { 
     public Byte[] RowVersionValue { get; set; } 
     public Int32? Somevalue { get; set; } 

     public static IEnumerable<SqlDataRecord> CreateSqlDataRecordEnumerable(IEnumerable<IRowVersionRecord> dataTransferObjects) 
     { 
      var sqlMetaData = new SqlMetaData[] 
      { new SqlMetaData("RowVersionValue", SqlDbType.Timestamp), 
       new SqlMetaData("somevalue", SqlDbType.Int) 
      }; 
      var record = new SqlDataRecord(sqlMetaData); 
      foreach (var dto in dataTransferObjects) 
      { 
       record.SetValue(0, dto.RowVersionValue); 
       record.SetValue(1, dto.Somevalue); 
       yield return record; 
      } 
     } 
    } 

    public partial class RowVersionRecord : RowVersionRecordBase 
    { 
    } 
} 

namespace MyApplication.DataAccess 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Data; 
    using System.Data.SqlClient; 

    public abstract class RowVersionDAOBase : DAO 
    { 
     public virtual void Upsert(IEnumerable<RowVersionRecord> values) 
     { 
      using (var connection = Connection) 
      { 
       using (var command = connection.CreateCommand()) 
       { 
        command.CommandType = CommandType.StoredProcedure; 
        command.CommandText = "RowVersion_Upsert"; 
        ((SqlCommand)command).Parameters.Add("@values", SqlDbType.Structured).Value = 
         (object)RowVersionRecordBase.CreateSqlDataRecordEnumerable(values) ?? (object)DBNull.Value;      
        using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess)) 
        { 
         while (reader.NextResult()) 
         { 
          ///..... 
         } 
        } 
       } 
      } 
     } 
    } 

    public partial class RowVersionDAO : RowVersionDAOBase 
    { 
    } 
} 

//Test code snip 
[TestMethod] 
public void RowVersionTVPTest() 
{ 
    RowVersionRecord record = new RowVersionRecord(); 
    record.Somevalue = 1; 
    List<RowVersionRecord> records = new List<RowVersionRecord>() 
    { 
     record 
    }; 
    using (RowVersionDAO dao = new RowVersionDAO()) 
    { 
     dao.Upsert(records); 
    } 
} 

回答

1

你永遠無法控制rowversion列的內容 - 但你表示要爲現有行提供特定值。

這將表示您應該使用binary(8) or varbinary(8)(分別取決於not-NULL/NULL)作爲TVP中該列的數據類型。

+0

我沒有在這裏得到的是,我可以有一個RowVersion作爲存儲過程的普通參數,我可以將一個值作爲一個字節傳遞給過程[8]。但是,如果我將TVP列聲明爲RowVersion,那麼我無法將該值指定爲byte [8]。我還沒有找到任何文檔說明在使用參數聲明時可以設置RowVersion類型,但不適用於TVP列。如果是這樣,爲什麼用戶定義的表類型有一個RowVersion列,如果它永遠不能被設置?或者可以和如何? –

+0

@RichardCollette - 它遵循表的規則,而不是參數的規則,因爲這不應該令人驚訝 - 例如在用戶定義的表類型中不能包含* 2 * rowversion列,但可以創建兩個rowversion類型的參數並將其傳遞給存儲過程。如果您有UDTT的局部變量,則該表中的任何「INSERT」或「UPDATE」都將遵循通常的預期規則。 –

+0

@Damien_TheUnbeliever我得到你對它的表現持續不變,但行爲不一致。在服務器上,您可以選擇一個UDTT,並將現有的行版本值複製到UDTT中。但是從ADO.NET中,我無法插入具有現有ROWVERSION值的行。不僅如此,但我無法指定傳遞給服務器的TVP行在RowVersion列中也有默認值。如果TVP是一個包含RowVersion列的UDTT,那麼TVP就不能在ADO.NET中使用(我還沒有看到它的一個例子)。 –

相關問題