Frage

Ich versuche, eine neue Art zu definieren und haben nicht viel Glück hatte keine Informationen zu finden, über Listen in ihnen. Grundsätzlich meine neue Art werden zwei Listen enthalten, können sagen, x und y vom Typ SqlSingle (der Benutzer definierten Typ in C # geschrieben) ist dies überhaupt möglich?

Wenn nicht, wie soll man gehen etwa zwei Listen einer willkürlichen Länge in einer SQL Server 2008 Spalt Simulation?

Ich werde vielleicht das über den falschen Weg, aber es ist der beste Ansatz, den ich von im Moment denken. Jede Hilfe wird sehr geschätzt.

War es hilfreich?

Lösung

Sie können eine List<T> in einer CLR UDT verwenden - obwohl CLR-Typen structs sind, die unveränderlich sein sollte, so ein ReadOnlyCollection<T> eine bessere Wahl wäre, wenn Sie nicht über einen sehr zwingenden Grund für die Veränderlichkeit haben. Was Sie brauchen in jedem Fall zu wissen ist, dass SQL nicht wissen, wie die Liste selbst zu verwenden; Sie können nicht einfach die Liste Typen als öffentliches IList<T> oder IEnumerable<T> aussetzen und auf fröhliche Art und Weise sein, wie Sie in der reinen .NET tun würden.

Typischerweise ist die Möglichkeit, dies zu umgehen, wäre eine Count Eigenschaft und einige Methoden belichten an den einzelnen Listenelemente zu erhalten.

Auch in diesem Fall anstelle von zwei separaten Listen von SqlSingle Instanzen beibehalten, würde ich eine zusätzliche Art schafft einen einzigen Punkt zu stellen, so dass Sie es unabhängig verwalten können und es in SQL-Pass um, wenn Sie benötigen:

[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.
}

Die wichtigste würde wie folgt aussehen:

[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; }
    }
}

Wenn Sie SQL müssen in der Lage sein, eine Sequenz aller Punkte zu bekommen, dann können Sie eine zählbare Methode, um den Sequenztyp als auch hinzufügen:

[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;
}

Man könnte denken, dass es möglich ist, eine IEnumerable<T> und / oder verwenden Sie eine Instanz-Methode anstelle eines statischen ein verwenden, aber nicht einmal die Mühe versucht, es funktioniert nicht.

So ist die Art und Weisen Sie den resultierenden Typen in SQL Server verwenden können, ist:

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)

Hope dies hilft Ihnen auf dem richtigen Weg zu bekommen. UDTs kann ziemlich kompliziert werden zu verwalten, wenn sie es zu tun mit einer Liste / Sequenzdaten.

Beachten Sie auch, dass Sie offensichtlich Serialisierungsmethoden benötigen hinzuzufügen, Generator-Methoden, zu aggregieren Methoden, und so weiter. Es kann durchaus eine Tortur sein; stellen Sie sicher, dass dies tatsächlich die Richtung Sie gehen in möchten, denn wenn Sie UDT Spalten beginnen Hinzufügen kann es sehr schwierig sein, Änderungen vorzunehmen, wenn Sie feststellen, dass Sie die falsche Wahl getroffen.

Andere Tipps

Listen, wie Sie beschreiben, sind in der Regel normalisieren -, die in separaten Tabellen mit einer Zeile pro Element gespeichert ist - anstatt zu versuchen, sie in eine einzige Spalte zu stopfen. Wenn Sie mehr Informationen zu teilen, was Sie versuchen zu erreichen, können wir vielleicht mehr Hilfe anbieten.

Bearbeiten - vorgeschlagen Tabellenstruktur:

-- 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>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top