Kodowanie typów zdefiniowanych przez użytkownika
Podczas kodowania definicję typ zdefiniowany przez użytkownika (UDT), musi implementować różnych funkcji, w zależności od tego, czy są wykonawczych UDT jako klasy lub struktury, jak również wybrane opcje formatu i serializacji.
W tej sekcji przykład ilustruje wykonawczych Point UDT jako struct (lub Structure w języku Visual Basic).Point UDT składa się z x i y współrzędne są implementowane jako właściwość procedur.
Podczas definiowania UDT wymagane są następujące obszary nazw:
Imports System
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
Microsoft.SqlServer.Server Nazw zawiera obiekty wymagane różne atrybuty użytkownika UDT i System.Data.SqlTypes nazw zawiera klasy, które reprezentują SQL Server macierzyste typy danych dostępne dla wirtualny plik dziennika.Oczywiście można dodatkowymi obszarami nazw użytkownika wirtualny plik dziennika wymaga, aby funkcja poprawnie.Point Używa również UDT System.Text obszaru nazw do pracy z ciągami.
Ostrzeżenie
Począwszy od SQL Server 2005, obiekty bazy danych Visual C++, takie jak UDTs, skompilowany z /clr:pure nie są obsługiwane przez wykonanie.
Określanie atrybutów
Atrybuty określają, jak serializacji jest używany do konstruowania reprezentacja Magazyn UDTs i przekazuje UDTs przez wartość do klient.
Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute Jest wymagane.name atrybut jest fakultatywne.Można również określić Microsoft.SqlServer.Server.SqlFacetAttribute do dostarczania informacji dotyczących zwrotu typu UDT.Aby uzyskać więcej informacji, zobacz Atrybuty niestandardowe dla procedur CLR.
Atrybuty punktu UDT
The Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute sets the storage format for the Point UDT to Native.IsByteOrdered is set to true, which guarantees that the results of comparisons are the same in SQL Server as if the same comparison had taken place in managed code.Implementuje UDT System.Data.SqlTypes.INullable interfejs, aby uświadomić UDT null.
Poniższy fragment kodu zawiera atrybuty dla Point UDT.
<Serializable(), SqlUserDefinedTypeAttribute(Format.Native, _
IsByteOrdered:=True)> _
Public Structure Point
Implements INullable
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native,
IsByteOrdered=true)]
public struct Point : INullable
{
Implementowanie Nullability
Oprócz określenia atrybuty użytkownika zestawów poprawnie UDT użytkownika musi obsługiwać opcje dopuszczania wartości null.Załadowane do UDTs SQL Server null obsługują, ale aby UDT rozpoznać wartości null, należy zaimplementować UDT System.Data.SqlTypes.INullable interfejs.
Należy utworzyć właściwość o nazwie IsNull, który jest potrzebny do ustalenia, czy wartość jest null od wewnątrz kodu CLR.Gdy SQL Server znajdzie null wystąpienie UDT UDT jest zachowywane przy użyciu zwykłych metod obsługi null.Serwer nie odpadów czas serializacji lub deserializacji UDT, jeśli nie ma na nie odpady miejsca do przechowywania null UDT.Ta kontrola dla wartości null jest wykonywana co czas UDT przenoszona z CLR, co oznacza, że za pomocą Transact-SQL konstrukcji IS NULL do sprawdzania null UDTs należy zawsze działa.IsNullwłaściwość Jest również używany przez serwer do sprawdzenia, czy instancja jest równa null. Gdy serwer określa, że UDT ma wartość null, może używać jego macierzystej obsługi null.
get() metoda IsNull jest nie specjalne pisane w dowolny sposób.Jeśli Point zmiennej @p jest Null, następnie @p.IsNull Domyślnie oceni "Null", nie "1".Wynika to z SqlMethod(OnNullCall) atrybut IsNull get() Domyślna metoda false.Ponieważ obiekt jest Null, gdy właściwość wymagane jest obiekt nie jest rozszeregować, nie zostanie wywołana metoda oraz wartość domyślną "Null" jest zwracany.
Przykład
W poniższym przykładzie is_Null zmienna jest prywatny i przechowuje stan null dla wystąpienie UDT.Kod należy utrzymać odpowiednią wartość dla is_Null.UDT musi także mieć właściwość statyczną o nazwie Null , zwraca wartość null wystąpienie UDT.Dzięki temu UDT zwraca wartość null, jeśli wystąpienie jest w rzeczywistości null w bazie danych.
Private is_Null As Boolean
Public ReadOnly Property IsNull() As Boolean _
Implements INullable.IsNull
Get
Return (is_Null)
End Get
End Property
Public Shared ReadOnly Property Null() As Point
Get
Dim pt As New Point
pt.is_Null = True
Return (pt)
End Get
End Property
private bool is_Null;
public bool IsNull
{
get
{
return (is_Null);
}
}
public static Point Null
{
get
{
Point pt = new Point();
pt.is_Null = true;
return pt;
}
}
JEST NULL vs.Funkcja IsNull
Należy rozważyć tabela, która zawiera punkty schematu (int identyfikator, punkt lokalizacji), gdzie Point jest CLR UDT i następujące kwerendy:
--Query 1
SELECT ID
FROM Points
WHERE NOT (location IS NULL) -- Or, WHERE location IS NOT NULL
--Query 2:
SELECT ID
FROM Points
WHERE location.IsNull = 0
Zarówno kwerendy zwracają identyfikatory punktów o nie-Null Lokalizacje.W kwerendzie 1 normalnej obsługi null jest używany i nie jest wymagane nie deserializacji UDTs.Kwerenda 2, z drugiej strony, ma do deserializacji każdego nie-Null object i wywołują CLR uzyskać wartość IsNull właściwość.Wyraźnie, za pomocą IS NULL będzie wykazywać większą wydajność i nigdy nie powinna powód, aby odczytać IsNull Właściwość UDT z Transact-SQL kodu.
Tak, co jest użycie IsNull Właściwość?Po pierwsze, jest potrzebny do ustalenia, czy wartość jest Null z kodu CLR.Po drugie, serwer musi sposobem sprawdzenia, czy wystąpienie jest Null, dlatego ta właściwość jest używana przez serwer.Po ustali ona jest Null, następnie można użyć, jego macierzystej null obsługi obsługi go
Implementowanie metody analizy
Parse i ToString metody umożliwiają konwersji do i z ciąg znaków reprezentującego UDT.Parse Metoda umożliwia ciąg do przekonwertowania na UDT.Musi być zadeklarowany jako static (lub Shared w języku Visual Basic) i parametr typu System.Data.SqlTypes.SqlString.
Następujący kod implementuje Parse metoda Point UDT, który oddziela się współrzędne x i Y.Parse Metoda ma pojedynczy argument typu System.Data.SqlTypes.SqlStringi przyjęto założenie, że wartości x i y są dostarczane jako ciąg rozdzielany przecinkami.Ustawienie Microsoft.SqlServer.Server.SqlMethodAttribute.OnNullCall atrybut false zapobiega Parse Metoda wywoływana z null wystąpienie punkt.
<SqlMethod(OnNullCall:=False)> _
Public Shared Function Parse(ByVal s As SqlString) As Point
If s.IsNull Then
Return Null
End If
' Parse input string here to separate out points.
Dim pt As New Point()
Dim xy() As String = s.Value.Split(",".ToCharArray())
pt.X = Int32.Parse(xy(0))
pt.Y = Int32.Parse(xy(1))
Return pt
End Function
[SqlMethod(OnNullCall = false)]
public static Point Parse(SqlString s)
{
if (s.IsNull)
return Null;
// Parse input string to separate out points.
Point pt = new Point();
string[] xy = s.Value.Split(",".ToCharArray());
pt.X = Int32.Parse(xy[0]);
pt.Y = Int32.Parse(xy[1]);
return pt;
}
Metoda ToString wykonawcze
ToString Konwertuje metoda Point UDT wartość ciąg.W tym przypadek ciąg znaków "NULL" zwrócone dla wystąpienie wartości Null Point typu.ToString Odwraca metoda Parse metoda za pomocą System.Text.StringBuilder do zwracania rozdzielany przecinkami System.String składający się z x i y współrzędnych wartości.Ponieważ InvokeIfReceiverIsNull wartością domyślną jest false, wyboru dla wystąpienie wartości null Point jest zbędne.
Private _x As Int32
Private _y As Int32
Public Overrides Function ToString() As String
If Me.IsNull Then
Return "NULL"
Else
Dim builder As StringBuilder = New StringBuilder
builder.Append(_x)
builder.Append(",")
builder.Append(_y)
Return builder.ToString
End If
End Function
private Int32 _x;
private Int32 _y;
public override string ToString()
{
if (this.IsNull)
return "NULL";
else
{
StringBuilder builder = new StringBuilder();
builder.Append(_x);
builder.Append(",");
builder.Append(_y);
return builder.ToString();
}
}
Uwidacznianie właściwości UDT
Point UDT uwidacznia współrzędne x i Y, które są implementowane jako publiczne właściwości odczytu i zapisu, typu System.Int32.
Public Property X() As Int32
Get
Return (Me._x)
End Get
Set(ByVal Value As Int32)
_x = Value
End Set
End Property
Public Property Y() As Int32
Get
Return (Me._y)
End Get
Set(ByVal Value As Int32)
_y = Value
End Set
End Property
public Int32 X
{
get
{
return this._x;
}
set
{
_x = value;
}
}
public Int32 Y
{
get
{
return this._y;
}
set
{
_y = value;
}
}
Sprawdzanie poprawności wartości UDT
Podczas pracy z danymi UDT Aparat baz danych programu SQL Server automatycznie konwertuje wartości binarnych UDT wartości.Ten proces konwersji obejmuje sprawdzenie, czy wartości są odpowiednie dla typu format serializacji i zapewnienie, że wartość można rozszeregować poprawnie.Dzięki temu można konwertować wartości do postaci binarnej.W przypadek z zamówionej bajt UDTs to również zapewnia zgodność wynikową wartość binarna oryginalna wartość binarna. Nieprawidłowe wartości zapobiega są zachowywane w bazie danych.W niektórych przypadkach może być nieodpowiednie sprawdzanie tego poziom.Dodatkowe sprawdzenie poprawności może być wymagane w UDT wartości są wymagane w oczekiwanym domena lub zakres.Na przykład UDT, który implementuje Data może wymagać wartość dnia na liczbę dodatnią, które wchodzą w zakres prawidłowych wartości.
The Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.ValidationMethodName property of the Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute allows you to supply the name of a validation method that the server runs when data is assigned to a UDT or converted to a UDT.ValidationMethodName is also called during the running of the bcp utility, BULK INSERT, DBCC CHECKDB, DBCC CHECKFILEGROUP, DBCC CHECKTABLE, distributed query, and tabular data stream (TDS) remote procedure call (RPC) operations.Wartość domyślna dla ValidationMethodName ma wartość null, wskazując, że istnieje nie metoda sprawdzania poprawności.
Przykład
Poniższy fragment kodu ilustruje deklaracja Point klasy, która określa ValidationMethodName z ValidatePoint.
<Serializable(), SqlUserDefinedTypeAttribute(Format.Native, _
IsByteOrdered:=True, _
ValidationMethodName:="ValidatePoint")> _
Public Structure Point
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native,
IsByteOrdered=true,
ValidationMethodName = "ValidatePoint")]
public struct Point : INullable
{
Jeśli określono metoda sprawdzania poprawności, musi on mieć podpis wygląda podobnie do następującego fragmentu kodu.
Private Function ValidationFunction() As Boolean
If (validation logic here) Then
Return True
Else
Return False
End If
End Function
private bool ValidationFunction()
{
if (validation logic here)
{
return true;
}
else
{
return false;
}
}
Metoda sprawdzania poprawności mogą mieć dowolny zakres i powinna zostać zwrócona true , jeśli wartość jest prawidłowa, a false inaczej.Jeśli metoda zwraca false lub rzuca przypadku wyjątkowego wartość jest traktowany jako nieprawidłowe i komunikat o błędzie jest wywoływane.
W poniższym przykładzie kodu umożliwia tylko wartości zero lub większa współrzędne x i Y.
Private Function ValidatePoint() As Boolean
If (_x >= 0) And (_y >= 0) Then
Return True
Else
Return False
End If
End Function
private bool ValidatePoint()
{
if ((_x >= 0) && (_y >= 0))
{
return true;
}
else
{
return false;
}
}
Ograniczenia metody sprawdzania poprawności
Serwer wywołuje metoda sprawdzania poprawności, gdy serwer wykonuje konwersje, nie po wstawionych danych, ustawiając właściwości poszczególnych lub wstawiane dane za pomocą Transact-SQL WSTAWIĆ instrukcja.
Należy jawnie wywołać metoda sprawdzania poprawności z ustawiające właściwość i analizy metoda, jeśli chcesz, aby metoda sprawdzania poprawności do wykonać we wszystkich sytuacjach.Nie jest to wymagane, a w niektórych przypadkach może nie być pożądane.
Przykład sprawdzania poprawności analizy
Zapewniające, że ValidatePoint wywoływana jest metoda punkt klasy, musisz wywołać ją z analizy metody i procedury właściwość, zestaw x i y wartości współrzędnych.Poniższy fragment kodu przedstawia sposób wywołania ValidatePoint metoda sprawdzania poprawności z analizy funkcja.
<SqlMethod(OnNullCall:=False)> _
Public Shared Function Parse(ByVal s As SqlString) As Point
If s.IsNull Then
Return Null
End If
' Parse input string here to separate out points.
Dim pt As New Point()
Dim xy() As String = s.Value.Split(",".ToCharArray())
pt.X = Int32.Parse(xy(0))
pt.Y = Int32.Parse(xy(1))
' Call ValidatePoint to enforce validation
' for string conversions.
If Not pt.ValidatePoint() Then
Throw New ArgumentException("Invalid XY coordinate values.")
End If
Return pt
End Function
[SqlMethod(OnNullCall = false)]
public static Point Parse(SqlString s)
{
if (s.IsNull)
return Null;
// Parse input string to separate out points.
Point pt = new Point();
string[] xy = s.Value.Split(",".ToCharArray());
pt.X = Int32.Parse(xy[0]);
pt.Y = Int32.Parse(xy[1]);
// Call ValidatePoint to enforce validation
// for string conversions.
if (!pt.ValidatePoint())
throw new ArgumentException("Invalid XY coordinate values.");
return pt;
}
Przykład sprawdzania poprawności właściwości
Poniższy fragment kodu przedstawia sposób wywołania ValidatePoint metoda sprawdzania poprawności z procedur właściwość, zestaw współrzędne x i Y.
Public Property X() As Int32
Get
Return (Me._x)
End Get
Set(ByVal Value As Int32)
Dim temp As Int32 = _x
_x = Value
If Not ValidatePoint() Then
_x = temp
Throw New ArgumentException("Invalid X coordinate value.")
End If
End Set
End Property
Public Property Y() As Int32
Get
Return (Me._y)
End Get
Set(ByVal Value As Int32)
Dim temp As Int32 = _y
_y = Value
If Not ValidatePoint() Then
_y = temp
Throw New ArgumentException("Invalid Y coordinate value.")
End If
End Set
End Property
public Int32 X
{
get
{
return this._x;
}
// Call ValidatePoint to ensure valid range of Point values.
set
{
Int32 temp = _x;
_x = value;
if (!ValidatePoint())
{
_x = temp;
throw new ArgumentException("Invalid X coordinate value.");
}
}
}
public Int32 Y
{
get
{
return this._y;
}
set
{
Int32 temp = _y;
_y = value;
if (!ValidatePoint())
{
_y = temp;
throw new ArgumentException("Invalid Y coordinate value.");
}
}
}
Metody kodowania UDT
Podczas kodowania UDT metody, należy rozważyć, czy algorytm używany ewentualnie można zmienić czas.Jeśli tak, możesz rozważyć utworzenia osobnej klasy dla metod swoje UDT używa.Jeśli zmienia algorytm, można ponownie skompilować klasy z nowym kodem i załadować wirtualny plik dziennika do SQL Server bez wpływu na UDT.W wielu przypadkach UDTs można wykorzystać przy użyciu Transact-SQL instrukcja ALTER zestawu, ale może powodować problemy z istniejących danych.Na przykład waluty dołączone UDT AdventureWorks2008R2 Przykładowa baza danych używa ConvertCurrency funkcja konwersji walut, który zaimplementowano w osobnej klasy.Jest możliwe, że algorytmów konwersji może zmienić w sposób nieprzewidywalny w przyszłości lub nowych funkcji mogą być wymagane.Oddzielenie ConvertCurrency funkcja z waluty wykonania UDT zapewnia większą elastyczność przy planowaniu przyszłych zmian.
Aby uzyskać informacje dotyczące sposobu instalowania AdventureWorks2008R2 CLR próbek, zobacz "Instalowanie próbkami" w SQL Server dokumentacji Books Online.
Przykład
Punkt klasa zawiera trzy proste metody obliczania odległość: Odległość, DistanceFrom i DistanceFromXY.Każdy zwraca double Obliczanie odległości od Point na zero, wskaż polecenie odległość od określonego Point, oraz współrzędne x i y do określonej odległości od Point.Odległość i DistanceFrom każdego wywołania DistanceFromXYi przedstawiają sposób zastosowania różnych argumentów dla każdej metoda.
' Distance from 0 to Point.
<SqlMethod(OnNullCall:=False)> _
Public Function Distance() As Double
Return DistanceFromXY(0, 0)
End Function
' Distance from Point to the specified point.
<SqlMethod(OnNullCall:=False)> _
Public Function DistanceFrom(ByVal pFrom As Point) As Double
Return DistanceFromXY(pFrom.X, pFrom.Y)
End Function
' Distance from Point to the specified x and y values.
<SqlMethod(OnNullCall:=False)> _
Public Function DistanceFromXY(ByVal ix As Int32, ByVal iy As Int32) _
As Double
Return Math.Sqrt(Math.Pow(ix - _x, 2.0) + Math.Pow(iy - _y, 2.0))
End Function
// Distance from 0 to Point.
[SqlMethod(OnNullCall = false)]
public Double Distance()
{
return DistanceFromXY(0, 0);
}
// Distance from Point to the specified point.
[SqlMethod(OnNullCall = false)]
public Double DistanceFrom(Point pFrom)
{
return DistanceFromXY(pFrom.X, pFrom.Y);
}
// Distance from Point to the specified x and y values.
[SqlMethod(OnNullCall = false)]
public Double DistanceFromXY(Int32 iX, Int32 iY)
{
return Math.Sqrt(Math.Pow(iX - _x, 2.0) + Math.Pow(iY - _y, 2.0));
}
Przy użyciu atrybutów SqlMethod
Microsoft.SqlServer.Server.SqlMethodAttribute Klasy zawiera atrybuty niestandardowe, które można oznaczyć definicji metody w celu określenia determinism na zachowanie wywołanie null i określić, czy metoda jest mutator.Przyjmowane są wartości domyślne dla tych właściwości i niestandardowy atrybut jest używany tylko w razie potrzeby wartości innej niż domyślna.
Ostrzeżenie
SqlMethodAttribute Klasa dziedziczy z SqlFunctionAttribute klasy tak SqlMethodAttribute dziedziczy FillRowMethodName i TableDefinition pola z SqlFunctionAttribute.Oznacza to, że jest możliwość pisania tabela-wycenione metodę, która nie jest dostępna.Metoda kompiluje i wirtualny plik dziennika wdraża, ale błąd o IEnumerable zwraca typ jest wywoływane w czasie wykonywania następujący komunikat: "Metody, właściwość, lub pole '<nazwę>" w klasie<klasy>" w zestawie '<wirtualny plik dziennika>" ma nieprawidłowy typ zwracany."
W poniższej tabela opisano niektóre odpowiednich Microsoft.SqlServer.Server.SqlMethodAttribute Właściwości, które mogą być używane w metodach UDT i wyświetla ich wartości domyślne.
DataAccess
Wskazuje, czy funkcja wymaga dostępu do danych użytkownika przechowywane w lokalnym wystąpienie SQL Server.Wartością domyślną jest DataAccessKind.None.IsDeterministic
Wskazuje, czy funkcja daje takie same wartości wyjściowych tej samej wartości wejściowych i tym samym stanie bazy danych.Wartością domyślną jest false.IsMutator
Wskazuje, czy metoda powoduje zmianę stanu UDT wystąpienie.Wartością domyślną jest false.IsPrecise
Wskazuje, czy funkcja obejmuje niedokładny obliczeń, takich jak ruchomy punkt operacji.Wartością domyślną jest false.OnNullCall
Wskazuje, czy metoda jest wywoływana po null podano argumenty wejściowe odniesienia.Wartością domyślną jest true.
Przykład
The Microsoft.SqlServer.Server.SqlMethodAttribute.IsMutator property allows you to mark a method that allows a change in the state of an instance of a UDT.Transact-SQL does not allow you to set two UDT properties in the SET clause of one UPDATE statement.Jednak może mieć metoda oznaczone jako mutator, który zmienia dwóch członków.
Ostrzeżenie
Metody mutator nie są dozwolone w kwerendach.One może zostać wywołana tylko w instrukcji modyfikacji danych lub instrukcji przypisania.Jeśli metoda oznaczona jako mutator nie zwraca void (lub nie jest Sub w języku Visual Basic), utworzyć typ nie powiedzie się z błąd.
Poniższa instrukcja zakłada istnienie Triangles UDT, który ma Rotate metoda.Następujące Transact-SQL Instrukcja update wywołuje Rotate metoda:
UPDATE Triangles SET t.RotateY(0.6) WHERE id=5
Rotate Ozdobione metody SqlMethod Ustawienie atrybut IsMutator do true , aby SQL Server można oznaczyć metody, jak metoda mutator.Kod ustawia również OnNullCall do false, która wskazuje na serwerze, metoda zwraca wartość null odniesienia (Nothing w języku Visual Basic) Jeśli parametry wejściowe będą odwołania zerowego.
<SqlMethod(IsMutator:=True, OnNullCall:=False)> _
Public Sub Rotate(ByVal anglex as Double, _
ByVal angley as Double, ByVal anglez As Double)
RotateX(anglex)
RotateY(angley)
RotateZ(anglez)
End Sub
[SqlMethod(IsMutator = true, OnNullCall = false)]
public void Rotate(double anglex, double angley, double anglez)
{
RotateX(anglex);
RotateY(angley);
RotateZ(anglez);
}
Implementowanie UDT format użytkownika
Podczas implementowania UDT formacie zdefiniowane przez użytkownika, należy zaimplementować Read i Write metod, które implementują interfejs Microsoft.SqlServer.Server.IBinarySerialize obsługę serializacji i podczas deserializacji danych UDT.Należy także określić MaxByteSize Właściwość Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.
Waluta UDT
Currency UDT jest dołączony do próbek CLR, które mogą być instalowane z SQL Server, począwszy od SQL Server 2005.Informacje dotyczące sposobu instalowania próbek CLR Zobacz Zagadnienia dotyczące instalowania przykładów i przykładowych baz danych programu SQL Server.
Currency UDT obsługuje obsługi kwot pieniędzy w systemie pieniężnej określonej kultury.Należy zdefiniować dwa pola: string dla CultureInfo, określa, kto wystawił waluty (en-us, na przykład) i decimal dla CurrencyValue, kwota pieniędzy.
Chociaż nie jest używany przez serwer do przeprowadzania porównań, Currency implementuje UDT System.IComparable interfejs, który udostępnia pojedynczą metoda System.IComparable.CompareTo.Używany w sytuacjach, gdy pożądane jest, aby dokładnie porównania lub kolejność wartości waluty w hodowlach po stronie klient.
Kod uruchomiony w środowisko CLR porównuje kultury, niezależnie od wartości waluty.Dla Transact-SQL Kod następujące akcje określają porównania:
Ustaw IsByteOrdered atrybut na true, która informuje o SQL Server do używania utrwalonej reprezentacja binarna na dysku dla porównań.
Użyj Write metoda Currency UDT, aby określić sposób utrwalone UDT na dysku, a więc jak UDT wartości są porównywane i dla Transact-SQL operacji.
Zapisz Currency w następującym formacie binarnym UDT:
Zapisz kultury jako ciąg zakodowany UTF-16 bajtów 0-19 z uzupełnienie prawo znakami null.
Użyj 20 bajtów i powyżej zawierają wartości dziesiętne waluty.
uzupełnienie ma na celu zapewnienie kultury jest całkowicie oddzielony od wartości waluty tak, aby po jednym UDT jest porównywany innego w Transact-SQL Kod, bajtów kultury są porównywane bajtów kultury i wartości bajtu waluty są porównywane wartości bajtu waluty.
Kompletny kod dla Currency UDT, wykonaj instrukcje dotyczące instalowania próbek CLR w Zagadnienia dotyczące instalowania przykładów i przykładowych baz danych programu SQL Server.
Atrybuty waluty
Currency UDT jest zdefiniowana z następujących atrybutów.
<Serializable(), Microsoft.SqlServer.Server.SqlUserDefinedType( _
Microsoft.SqlServer.Server.Format.UserDefined, _
IsByteOrdered:=True, MaxByteSize:=32), _
CLSCompliant(False)> _
Public Structure Currency
Implements INullable, IComparable, _
Microsoft.SqlServer.Server.IBinarySerialize
[Serializable]
[SqlUserDefinedType(Format.UserDefined,
IsByteOrdered = true, MaxByteSize = 32)]
[CLSCompliant(false)]
public struct Currency : INullable, IComparable, IBinarySerialize
{
Tworzenie zapisu i odczytu metod interfejsu IBinarySerialize
Po wybraniu UserDefined format serializacji również należy zaimplementować IBinarySerialize interfejs i tworzyć swoje własne Read i Write metody.Poniższe procedury z Currency wykorzystania UDT System.IO.BinaryReader i System.IO.BinaryWriter do odczytu i zapisu UDT.
' IBinarySerialize methods
' The binary layout is as follow:
' Bytes 0 - 19: Culture name, padded to the right with null
' characters, UTF-16 encoded
' Bytes 20+: Decimal value of money
' If the culture name is empty, the currency is null.
Public Sub Write(ByVal w As System.IO.BinaryWriter) _
Implements Microsoft.SqlServer.Server.IBinarySerialize.Write
If Me.IsNull Then
w.Write(nullMarker)
w.Write(System.Convert.ToDecimal(0))
Return
End If
If cultureName.Length > cultureNameMaxSize Then
Throw New ApplicationException(String.Format(CultureInfo.CurrentUICulture, _
"{0} is an invalid culture name for currency as it is too long.", cultureNameMaxSize))
End If
Dim paddedName As String = cultureName.PadRight(cultureNameMaxSize, CChar(vbNullChar))
For i As Integer = 0 To cultureNameMaxSize - 1
w.Write(paddedName(i))
Next i
' Normalize decimal value to two places
currencyVal = Decimal.Floor(currencyVal * 100) / 100
w.Write(currencyVal)
End Sub
Public Sub Read(ByVal r As System.IO.BinaryReader) _
Implements Microsoft.SqlServer.Server.IBinarySerialize.Read
Dim name As Char() = r.ReadChars(cultureNameMaxSize)
Dim stringEnd As Integer = Array.IndexOf(name, CChar(vbNullChar))
If stringEnd = 0 Then
cultureName = Nothing
Return
End If
cultureName = New String(name, 0, stringEnd)
currencyVal = r.ReadDecimal()
End Sub
// IBinarySerialize methods
// The binary layout is as follow:
// Bytes 0 - 19:Culture name, padded to the right
// with null characters, UTF-16 encoded
// Bytes 20+:Decimal value of money
// If the culture name is empty, the currency is null.
public void Write(System.IO.BinaryWriter w)
{
if (this.IsNull)
{
w.Write(nullMarker);
w.Write((decimal)0);
return;
}
if (cultureName.Length > cultureNameMaxSize)
{
throw new ApplicationException(string.Format(
CultureInfo.InvariantCulture,
"{0} is an invalid culture name for currency as it is too long.",
cultureNameMaxSize));
}
String paddedName = cultureName.PadRight(cultureNameMaxSize, '\0');
for (int i = 0; i < cultureNameMaxSize; i++)
{
w.Write(paddedName[i]);
}
// Normalize decimal value to two places
currencyValue = Decimal.Floor(currencyValue * 100) / 100;
w.Write(currencyValue);
}
public void Read(System.IO.BinaryReader r)
{
char[] name = r.ReadChars(cultureNameMaxSize);
int stringEnd = Array.IndexOf(name, '\0');
if (stringEnd == 0)
{
cultureName = null;
return;
}
cultureName = new String(name, 0, stringEnd);
currencyValue = r.ReadDecimal();
}
Kompletny kod dla Currency UDT, zobacz Zagadnienia dotyczące instalowania przykładów i przykładowych baz danych programu SQL Server.