2013-11-01 1 views
2

아래 코드와 같이 RowVersion 열을 포함하는 SQLDataRecord가있는 경우. 나는 항상 프로토콜 스트림이 잘못되는 SQL 서버 오류 8052저장 프로 시저를 호출 할 때 테이블 값 매개 변수에 RowVerson 열을 포함하려면 어떻게합니까?

들어오는 테이블 형식 데이터 스트림 (TDS) 원격 프로 시저 호출 (RPC)을 얻는다. 테이블 값 매개 변수 % d ("%. * ls"), 행 % I64d, 열 % d : 데이터 형식 0x % 02X (사용자 정의 테이블 형식) 타임 스탬프 열이 기본값이어야합니다.

RowVersion 값을 null 또는 값으로 설정했는지 여부.

기존 레코드에 대해 RowVersion 값을 보내고 ADO.NET에서 저장 프로 시저로 새 레코드를 보내고 싶을 때 레코드 병합시 옵토 믹스 동시성 검사를 사용할 수 있습니다.

어떻게이 작업을 수행 할 수 있습니까?

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 열의 내용을 제어 할 수 없다 - 그러나 당신은 당신이 기존 행에 대한 특정 값을 제공 할 것을 지시했습니다.

그러면 TVP의 해당 열에 대한 데이터 형식으로 binary(8) or varbinary(8) (각각 NULL이 아닌/NULL에 따라 다름)을 사용해야 함을 나타냅니다.

+0

내가 여기에 오지 않는다는 것은 스토어드 프로 시저에 대한 일반 매개 변수로 RowVersion을 가질 수 있으며 프로 시저에 값을 바이트로 전달할 수 있다는 것입니다. 그러나 TVP 열을 RowVersion으로 선언하면 값을 byte [8]로 지정할 수 없습니다. 매개 변수 선언과 함께 사용할 때 RowVersion 유형을 설정할 수 있지만 TVP 열은 사용할 수 없다는 어떠한 문서도 찾지 못했습니다. 그렇다면 결코 정의 될 수없는 경우 사용자 정의 테이블 유형에 RowVersion 열이있을 수 있습니까? 아니면 어떻게 할 수 있습니까? –

+0

@RichardCollette - 매개 변수에 대한 규칙보다는 테이블에 대한 규칙을 따르고 있습니다. 사용자 정의 테이블 유형에 * row * 열을 둘 수는 없지만 rowversion 유형의 두 매개 변수를 작성하여 저장 프로 시저에 전달할 수 있습니다. 그리고 만약 당신이 UDTT의 지역 변수를 가지고 있다면, 그 테이블에 대한'INSERT' 나'UPDATE'는 보통의 예상 규칙을 따릅니다. –

+0

@Damien_TheUnbeliever 일관되게 행동하는 것에 대해 당신이 말하는 것을 얻지 만, 일관되게 행동하지 않습니다. 서버에서 UDTT로 선택할 수 있으며 기존 행 버전 값이 UDTT에 복사됩니다. 하지만 ADO.NET에서는 기존 ROWVERSION 값을 가진 행을 삽입 할 방법이 없습니다. 뿐만 아니라, 나는 서버에 전달할 TVP 행에 RowVersion 열의 기본값도 지정하도록 지정할 수 없습니다. TVP가 RowVersion 열을 포함하는 UDTT 인 경우 ADP.NET에서 TVP를 사용할 수 없습니다 (아직 예제가 없습니다). –

관련 문제