Вопрос

Я пытаюсь определить новый тип и не повезло найти какую-либо информацию об использовании списков внутри них. По сути, мой новый тип будет содержать два списка, позволяет сказать x и y типа sqlsingle (пользовательский тип написан в C #) Это даже возможно?

Если нет, как вы должны продолжать имитировать два списка артистики в столбце SQL Server 2008?

Я, возможно, делаю это неправильно, но это лучший подход, который я могу подумать в данный момент. Любая помощь очень ценится.

Это было полезно?

Решение

Вы можете использовать List<T> в CLR UDT - хотя типы CLR являются структурами, которые должны быть неизменными, поэтому ReadOnlyCollection<T> будет лучшим выбором, если у вас нет очень убедительной причины для мультиплизма. То, что вам нужно знать, в любом случае, это то, что SQL не будет знать, как использовать сам список; Вы не можете просто разоблачить тип списка как публичный IList<T> или IEnumerable<T> И будьте на свой веселый путь, как вы сможете сделать в чистом виде .NET.

Как правило, способ обойти это было бы выдержать Count Собственность и некоторые методы, чтобы получить в отдельных элементах списка.

Кроме того, в этом случае вместо поддержания двух отдельных списков SqlSingle Исполнения, я бы создал дополнительный тип, чтобы представлять одну точку, чтобы вы могли управлять им самостоятельно и передавать его в SQL, если вам нужно:

[Serializable]
[SqlUserDefinedType(Format.Native)]
public struct MyPoint
{
    private SqlSingle x;
    private SqlSingle y;

    public MyPoint()
    {
    }

    public MyPoint(SqlSingle x, SqlSingle y) : this()
    {
        this.x = x;
        this.y = y;
    }

    // You need this method because SQL can't use the ctors
    [SqlFunction(Name = "CreateMyPoint")]
    public static MyPoint Create(SqlSingle x, SqlSingle y)
    {
        return new MyPoint(x, y);
    }

    // Snip Parse method, Null property, etc.
}

Главный тип будет выглядеть что-то подобное:

[Serializable]
[SqlUserDefinedType(Format.UserDefined, IsByteOrdered = true, MaxByteSize = ...)]
public struct MyUdt
{
    // Make sure to initialize this in any constructors/builders
    private IList<MyPoint> points;

    [SqlMethod(OnNullCall = false, IsDeterministic = true, IsPrecise = true)]
    public MyPoint GetPoint(int index)
    {
        if ((index >= 0) && (index < points.Count))
        {
            return points[index];
        }
        return MyPoint.Null;
    }

    public int Count
    {
        get { return points.Count; }
    }
}

Если вам нужен SQL, чтобы иметь возможность получить последовательность всех точек, вы можете добавить перечислимый метод к типу последовательности:

[SqlFunction(FillRowMethodName = "FillPointRow",
    TableDefinition = "[X] real, [Y] real")]
public static IEnumerable GetPoints(MyUdt obj)
{
    return obj.Points;
}

public static void FillPointRow(object obj, out SqlSingle x, out SqlSingle y)
{
    MyPoint point = (MyPoint)obj;
    x = point.X;
    y = point.Y;
}

Вы можете подумать, что можно использовать IEnumerable<T> и / или использовать метод экземпляра вместо статического, но даже не беспокоиться, это не работает.

Таким образом, как вы можете использовать полученный тип в SQL Server:

DECLARE @UDT MyUdt
SET @UDT = <whatever>

-- Will show the number of points
SELECT @UDT.Count

-- Will show the binary representation of the second point
SELECT @UDT.GetPoint(1) AS [Point]

-- Will show the X and Y values for the second point
SELECT @UDT.GetPoint(1).X AS [X], @UDT.GetPoint(1).Y AS [Y]

-- Will show all the points
SELECT * FROM dbo.GetPoints(@UDT)

Надеюсь, это поможет вам на правильном пути. УДЦ может быть довольно сложным, чтобы управлять, когда они имеют дело со списком / последовательностью данных.

Также обратите внимание, что вы, очевидно, нужно добавить методы сериализации, методы строителя, совокупные методы и так далее. Это может быть довольно испытательным; Убедитесь, что это на самом деле, это направление, которое вы хотите войти, потому что, как только вы начнете добавлять столбцы UDT, может быть очень сложно внести изменения, если вы понимаете, что вы сделали неправильный выбор.

Другие советы

Списки, как вы описываете, обычно нормируются - то есть, хранятся в отдельных таблицах с одной строкой на предмет - вместо того, чтобы пытаться пройти их в один столбец. Если вы можете поделиться дополнительной информацией о том, что вы пытаетесь выполнить, возможно, мы можем предложить дополнительную помощь.

Редактировать - Предлагаемая структура таблицы:

-- route table--
route_id      int   (PK)
route_length  int (or whatever)
route_info    <other fields as needed>

-- waypoint table --
route_id      int      (PK)
sequence      tinyint  (PK)
lat           decimal(9,6)
lon           decimal(9,6)
waypoint_info <other fields as needed>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top