Udostępnij przez


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:

  1. Ustaw IsByteOrdered atrybut na true, która informuje o SQL Server do używania utrwalonej reprezentacja binarna na dysku dla porównań.

  2. 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.

  3. Zapisz Currency w następującym formacie binarnym UDT:

    1. Zapisz kultury jako ciąg zakodowany UTF-16 bajtów 0-19 z uzupełnienie prawo znakami null.

    2. 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.