我試圖定義一個新類型,並沒有太多的運氣找到任何關於使用列表中的信息。基本上我的新類型將包含兩個列表,讓我們說SqlSingle類型的x和y(用戶定義的類型是用C#編寫的),這甚至可能嗎?用戶定義類型列表(SQL Server 2008)
如果不是你應該如何去模擬SQL Server 2008專欄中的兩個任意長度的列表?
我可能會以這種錯誤的方式去做,但這是我現在能想到的最好的方法。很感謝任何形式的幫助。
我試圖定義一個新類型,並沒有太多的運氣找到任何關於使用列表中的信息。基本上我的新類型將包含兩個列表,讓我們說SqlSingle類型的x和y(用戶定義的類型是用C#編寫的),這甚至可能嗎?用戶定義類型列表(SQL Server 2008)
如果不是你應該如何去模擬SQL Server 2008專欄中的兩個任意長度的列表?
我可能會以這種錯誤的方式去做,但這是我現在能想到的最好的方法。很感謝任何形式的幫助。
您可以在CLR UDT使用List<T>
- 雖然CLR類型結構,這應該是不變的,所以如果你不」一個ReadOnlyCollection<T>
將是一個更好的選擇對於可變性來說,有一個非常有說服力的理由。無論是哪種情況,你都需要知道SQL不知道如何使用列表本身;您不能簡單地將列表類型公開爲公開的IList<T>
或IEnumerable<T>
,並以您的快樂方式,就像您可以在純.NET中執行的一樣。
通常情況下,解決這個問題的方法是公開一個Count
屬性和一些方法來獲取各個列表項。在這種情況下,我將創建一個附加類型來表示單個點,因此如果需要,您可以獨立管理它並在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>
基本上我試圖創建的類型是一條路線。每條路線可以包含任意數量的航點。每個航點都是經緯度。 路線應被視爲離散類型,並且必須與給定的用戶ID相關聯。 – Cromulent 2010-03-07 16:19:27
我對路由'n'的東西瞭解不多。但通常在規範化的數據庫中,您將擁有包含路由標識(或用戶標識或任何您需要的)的路由表。然後是一個航點表,它將具有來自路線表的ID,加上航點ID或序號,以及該點的經緯度數據。每個航點在此表中都有單獨的記錄。 – Ray 2010-03-07 16:32:54
該方法的問題是需要一個單獨的列來跟蹤每條路線的長度,每條路線的起點路標ID以及每條路線的終點路標ID,以確保您不會意外地從在表格之後或之前的路線。這就是爲什麼我想要使用一個列表,因爲所有這些都是照顧好的。除了在每條路線的範圍內使用它們之外,我沒有其他方法可以使用它們,而且我也希望所有與該路線相關的其他航點都在同一時間。 – Cromulent 2010-03-07 16:42:06
謝謝,這非常有幫助。 – Cromulent 2010-03-08 07:40:49