using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined, MaxByteSize = 2048)]
public struct SqlIntArray : INullable, IBinarySerialize {
private int[] _array;
private bool m_Null;
public override string ToString() {
if (IsNull)
return "NULL";
StringBuilder sb = new StringBuilder();
sb.Append("{");
foreach (int number in _array ?? new int[0]) {
sb.Append(" ");
sb.Append(number.ToString());
}
sb.Append(" }");
return sb.ToString();
}
public bool IsNull {
get {
// Put your code here
return m_Null;
}
}
public static SqlIntArray Null {
get {
SqlIntArray h = new SqlIntArray();
h.m_Null = true;
return h;
}
}
private static readonly Regex regex = new Regex(@"^\s*{(\s*\d+)*\s*}\s*$",
RegexOptions.Compiled);
public static SqlIntArray Parse(SqlString s) {
if (s.IsNull)
return Null;
if (regex.IsMatch(s.Value)) {
SqlIntArray u = new SqlIntArray();
string[] numbers = s.Value.Split(new char[] { '{', '}', ' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
u._array = Array.ConvertAll<string, int>(numbers, int.Parse);
return u;
} else
return Null;
}
// This is a place-holder method
public int[] ToArray() {
return _array ?? new int[0];
}
#region IBinarySerialize Members
public void Read(System.IO.BinaryReader r) {
m_Null = r.ReadBoolean();
if(!m_Null) {
int length = r.ReadInt32();
_array = new int[length];
for(int i = 0; i < length; ++i) {
_array = r.ReadInt32();
}
}
}
public void Write(System.IO.BinaryWriter w) {
w.Write(m_Null);
if(!m_Null) {
int length = _array.Length;
w.Write(length);
for (int i = 0; i < length; ++i) {
w.Write(_array);
}
}
}
#endregion
}
Передача списка в хранимую процедуру MS SQL Server
Дамы и господа! Есть CLR хранимая процедура в базе данных MS SQL Server 2005. Необходимо передать туда список/массив значений типа SqlInt64. Заменить передачу списка параметров многократным вызовом процедуры с разными параметрами нельзя - нужен именно список. Так вот, как такое разрулить?
Цитата: Der Meister
Так вот, как такое разрулить?
Создать собственный CLR-тип данных, инкапсулирующий сисок чего-либо, и уже передавать его.
Смущает мя лишь одно: вроде как, пользовательские типы там могут включать в себя лишь экземляры объектов значащих типов (value-type objects)
Цитата: Der Meister
Смущает мя лишь одно: вроде как, пользовательские типы там могут включать в себя лишь экземляры объектов значащих типов (value-type objects)
Вот пример:
Код:
Код:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void StoredProcedure1(SqlIntArray list) {
foreach(int i in list.ToArray()) {
SqlContext.Pipe.Send(i.ToString());
}
}
public static void StoredProcedure1(SqlIntArray list) {
foreach(int i in list.ToArray()) {
SqlContext.Pipe.Send(i.ToString());
}
}
Код:
DECLARE @return_value int
EXEC @return_value = [dbo].[StoredProcedure1]
@list = '{12 34 56}'
SELECT 'Return Value' = @return_value
EXEC @return_value = [dbo].[StoredProcedure1]
@list = '{12 34 56}'
SELECT 'Return Value' = @return_value
Тип писал "абы работало" там есть кривые места - ограничение размера списка т.к. сиквелу нужно знать сколько будет максимально весить экземпляр объекта:
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined, MaxByteSize = 2048)]
Ну и четкая валидация в методе Parse.
Спасибо! Бум с размерами разбираться...