我试图定义一个新的类型,并没有太多的运气找到如何使用它们内部列出的任何信息。基本上我的新类型将包含两个列表,可以说x和类型SqlSingle(用户定义的类型是写在C#),则这甚至可能?

Y的

如果没有,你应该如何去在SQL Server 2008中柱模拟的arbitary长度的两个列表?

我可能要对这个错误的方式,但它是我能在那一刻想到的最好的办法。任何帮助非常赞赏。

有帮助吗?

解决方案

您可以使用在CLR UDT一个List<T> - 虽然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的可以得到相当复杂的管理时,他们正在处理的列表/序列数据。

另外请注意,您会明显地需要添加序列化方法,生成器方法,聚合方法,等等。它可以是相当严峻的考验;确保这其实是你想要去的,因为一旦你开始增加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