Вставка строковых данных в столбец определяемого пользователем типа данных Varbinary SQL Server .NET
У меня есть требование вставлять записи в таблицу SQL, которая содержит столбцы varbinary и image.
Как получить 0x00120A011EFD89F94DDA363BA64F57441DE9 (это одинаково для всех записей)
в это
BLOB_TYPE (MY_UDDT(varbinary(18))?
Это то, что у меня есть, все очень просто, за исключением определения параметра SqlDbType.Udt. С помощью этого кода я получаю сообщение об ошибке: "Указанный тип не зарегистрирован на целевом сервере.System.Byte[]", я могу сказать, что на сервере 100% "Определяемый пользователем тип данных". Я запросил select * from sys.types, и он вернул тип.
Определение: CREATE TYPE [dbo].[MY_UDDT] ИЗ varbinary NOT NULL
sql = "INSERT INTO dbo.BLOBS (BLOB_TYPE) VALUES (@BLOB_TYPE);"
cmd = New SqlCommand(sql, conn)
Dim parameter As New SqlParameter("@BLOB_TYPE", SqlDbType.Udt)
With parameter
.SqlDbType = SqlDbType.Udt
.UdtTypeName = "dbo.MY_UDDT"
.Value = blobType
End With
cmd.Parameters.Add(parameter)
cmd.ExecuteNonQuery()
Public ReadOnly Property blobType As Byte()
Get
Dim Str As String = "0x00620A011EFD89F94DDA863BA64F57441DE9"
Dim bytes As Byte() = New Byte(Str.Length * 2 - 1) {}
System.Buffer.BlockCopy(Str.ToCharArray(), 0, bytes, 0, bytes.Length)
Return bytes
End Get
End Property
3 ответа
Есть несколько вещей, которые неправильно понимаются здесь:
- Существует большая разница между пользовательскими типами данных (UDDT) и пользовательскими типами (UDT), хотя вполне понятно, что люди путаются из-за сходства имен.
- Что вы создали с помощью
CREATE TYPE
это UDDT, а не UDT. Это конструкция только для T-SQL. - Примечание на будущее: при указании типа данных переменной длины обязательно указывайте длину:
VARBINARY(18)
вместоVARBINARY
- UDT является конструкцией SQLCLR. Вот пример на MSDN использования UDT таким образом:
http://msdn.microsoft.com/library/ms131080.aspx
- Что вы создали с помощью
- Вам не нужно ничего особенного здесь. Вам просто нужно установить:
SqlDbType = SqlDbType.VarBinary
Size = 18
Ваш
blobType
Функция не отправляет шестнадцатеричное представление ожидаемой вами строки. Он отправляет шестнадцатеричные значения для каждого символа строки "0x00620A011EFD89F94DDA863BA64F57441DE9". Это означает, что шестнадцатеричное значение для "0" (т.е. 48 или 0x30), затем шестнадцатеричное значение для "x" (т.е. 120 или 0x78) и т. Д. Для всех 38 символов.Вам нужно взять каждый набор из 2 символов после "0x" (то есть "00", затем "62", затем "0A" и т. Д.), Преобразовать их в фактические байты и отправить массив.
ИЛИ ЖЕ
Если у вас есть значения в VB в виде строк и вы используете SQL Server 2008 или новее, вы можете передать строку и сделать так, чтобы SQL Server преобразовал ее для вас. Вы просто изменили бы свой оператор INSERT так:
INSERT INTO dbo.BLOBS (BLOB_TYPE) VALUES (CONVERT(VARBINARY(18), @BLOB_TYPE, 1));
CONVERT
Функция, используя стиль "1" (что означает: строковое представление двоичного файла, начиная с "0x"), добьется цели. Например:SELECT CONVERT(VARBINARY(18), '0x00620A011EFD89F94DDA863BA64F57441DE9', 1)
Конечно, тогда вам нужно изменить
SqlParameter
свойства быть:SqlDbType = SqlDbType.VarChar
Size = 38
Проблема заключается в том, что значение параметра является байтовым массивом, а не экземпляром UDT, в который, как вы утверждаете, будет передаваться, и System.Byte[]
неудивительно, что это не зарегистрированный UDT.
Это сбивает с толку, но "UDT" на стороне.NET используется только для UDT, которые создаются в сборках (CREATE TYPE ... EXTERNAL NAME
) и не для UDT, основанных на типах SQL Server (называемых "типами данных псевдонимов" в Books Online). Чтобы пройти те, не устанавливайте SqlDbType
в Udt
но просто передайте значение базового базового типа. По сути, эти типы полезны только на стороне базы данных для обеспечения согласованности.
Кроме того, вы создаете блоб неправильно - вам нужно преобразовать шестнадцатеричную строку в байты, а не символы, составляющие шестнадцатеричную строку. Если это действительно константа, вы можете объявить ее таковой. Так:
cmd.Parameters.AddWithValue("@BLOB_TYPE", New Byte() { &H00, &H62, &H0A, &H01, &H1E, &HFD, &H89, &HF9, &H4D, &HDA, &H86, &H3B, &HA6, &H4F, &H57, &H44, &H1D, &HE9 })
Должен сделать свое дело.
SqlDbType.Udt для типов SQLCLR. В этом случае у вас есть столбец varbinary, поэтому укажите SqlDbType.VarBinary вместе с максимальным размером (18). В качестве значения передайте байтовый массив, содержащий необработанное двоичное значение.
Вы упоминаете 18-байтовый тип данных varbinary, но данные выглядят намного длиннее. Если вы намереваетесь преобразовать строку в шестнадцатеричном формате в 18-байтовое двоичное значение, это другой вопрос, чем тот, который здесь задавался. Я предлагаю вам опубликовать еще один вопрос, если вам нужна помощь с этим.