Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Kullanıcı tanımlı tür (UDT) tanımınızı kodlarken, UDT'yi sınıf olarak mı yoksa yapı olarak mı uyguladığınıza ve seçtiğiniz biçim ve serileştirme seçeneklerine bağlı olarak çeşitli özellikleri uygulamanız gerekir.
Bu bölümdeki örnekte, Point
UDT'nin struct
(veya Visual Basic'te Structure
) olarak uygulanması gösterilmektedir.
Point
UDT, özellik yordamları olarak uygulanan X ve Y koordinatlarından oluşur.
UDT tanımlarken aşağıdaki ad alanları gereklidir:
-
C#
-
Visual Basic .NET
using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
Microsoft.SqlServer.Server
ad alanı, UDT'nizin çeşitli öznitelikleri için gereken nesneleri içerir ve System.Data.SqlTypes
ad alanı, derlemede kullanılabilen SQL Server yerel veri türlerini temsil eden sınıfları içerir. Derlemenizin düzgün çalışması için gereken başka ad alanları da olabilir.
Point
UDT, dizelerle çalışmak için System.Text
ad alanını da kullanır.
Not
/clr:pure
ile derlenen UDT'ler gibi Visual C++ veritabanı nesneleri yürütme için desteklenmez.
Öznitelikleri belirtme
Öznitelikler, UDT'lerin depolama gösterimini oluşturmak ve UDT'leri değere göre istemciye iletmek için serileştirmenin nasıl kullanıldığını belirler.
Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute
gereklidir.
Serializable
özniteliği isteğe bağlıdır. Ayrıca, UDT'nin dönüş türü hakkında bilgi sağlamak için Microsoft.SqlServer.Server.SqlFacetAttribute
belirtebilirsiniz. Daha fazla bilgi için bkz. CLR tümleştirmesi:CLR yordamları için özel öznitelikler.
Nokta UDT öznitelikleri
Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute
, Point
UDT için depolama biçimini Native
olarak ayarlar.
IsByteOrdered
true
olarak ayarlanır ve bu da sql Server'da karşılaştırma sonuçlarının yönetilen kodda aynı karşılaştırmanın gerçekleştiği gibi aynı olmasını garanti eder. UDT, UDT null değerinin farkında olmasını sağlamak için System.Data.SqlTypes.INullable
arabirimini uygular.
Aşağıdaki kod parçası, Point
UDT özniteliklerini gösterir.
-
C#
-
Visual Basic .NET
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native,
IsByteOrdered=true)]
public struct Point : INullable { ... }
Null atanabilirlik uygulama
Derlemeleriniz için öznitelikleri doğru belirtmeye ek olarak, UDT'nizin de null atanabilirliği desteklemesi gerekir. SQL Server'a yüklenen UDF'ler null algılamalıdır, ancak UDT'nin null değeri tanıması için UDT'nin System.Data.SqlTypes.INullable
arabirimini uygulaması gerekir.
CLR kodu içinden bir değerin null olup olmadığını belirlemek için gereken IsNull
adlı bir özellik oluşturmanız gerekir. SQL Server bir UDT'nin null örneğini bulduğunda, UDT normal null işleme yöntemleri kullanılarak kalıcı hale gelir. Sunucu, gerekirse UDT'yi seri hale getirmek veya seri durumdan çıkartmak için zaman kaybetmez ve null UDT depolamak için alan harcamaz. Bu null denetimi, CLR'den bir UDT getirildiğinde gerçekleştirilir ve bu da null UDT'leri denetlemek için Transact-SQL IS NULL
yapısını kullanmanın her zaman çalışması gerektiği anlamına gelir.
IsNull
özelliği de sunucu tarafından bir örneğin null olup olmadığını test etmek için kullanılır. Sunucu UDT'nin null olduğunu belirledikten sonra yerel null işlemesini kullanabilir.
IsNull
get()
yöntemi herhangi bir şekilde özel durumla ilgili değildir.
@p
Point
değişkeni Null
ise @p.IsNull
varsayılan olarak 1
değil NULL
olarak değerlendirilir. Bunun nedeni, IsNull get()
yönteminin SqlMethod(OnNullCall)
özniteliğinin varsayılan olarak false olmasıdır. nesnesi Null
olduğundan, özellik istendiğinde nesne seri durumdan çıkarılamaz, yöntem çağrılmaz ve varsayılan "NULL" değeri döndürülür.
Örnek
Aşağıdaki örnekte is_Null
değişkeni özeldir ve UDT örneği için null durumunu tutar. Kodunuz is_Null
için uygun bir değer tutmalıdır. UDT ayrıca UDT'nin null değer örneğini döndüren Null
adlı bir statik özelliğe de sahip olmalıdır. Bu, örneğin veritabanında gerçekten null olması durumunda UDT'nin null değer döndürmesine olanak tanır.
-
C#
-
Visual Basic .NET
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;
}
}
IS NULL ile IsNull karşılaştırması
Point
bir CLR UDT olduğu Points(id int, location Point)
şemasını ve aşağıdaki sorguları içeren bir tablo düşünün:
Sorgu 1:
SELECT ID FROM Points WHERE NOT (location IS NULL); -- Or, WHERE location IS NOT NULL;
Sorgu 2:
SELECT ID FROM Points WHERE location.IsNull = 0;
Her iki sorgu da null olmayan konumlara sahip noktaların kimliklerini döndürür. Sorgu 1'de normal null işleme kullanılır ve UDF'lerin seri durumdan çıkarılması gerekmez. Öte yandan sorgu 2'nin null olmayan her nesneyi seri durumdan çıkarması ve IsNull
özelliğinin değerini almak için CLR'ye çağırması gerekir. Açıkçası, IS NULL
kullanmak daha iyi bir performans sergiler ve bir UDT'nin IsNull
özelliğini Transact-SQL koddan okumak için hiçbir zaman bir neden olmamalıdır.
Peki, IsNull
özelliğinin kullanımı nedir? İlk olarak, CLR kodu içinden bir değerin null olup olmadığını belirlemek için gereklidir. İkinci olarak, sunucunun bir örneğin null olup olmadığını test etmek için bir yönteme ihtiyacı vardır, bu nedenle bu özellik sunucu tarafından kullanılır. Null olarak belirlendikten sonra, bunu işlemek için yerel null işlemesini kullanabilir.
Ayrıştırma yöntemini uygulama
Parse
ve ToString
yöntemleri, UDT'nin dize gösterimlerine ve bu gösterimlerden dönüştürmelere olanak sağlar.
Parse
yöntemi bir dizenin UDT'ye dönüştürülmesini sağlar.
static
(veya Visual Basic'te Shared
) olarak bildirilmeli ve System.Data.SqlTypes.SqlString
türünde bir parametre almalıdır.
Aşağıdaki kod, X ve Y koordinatlarını ayıran Point
UDT için Parse
yöntemini uygular.
Parse
yöntemi, System.Data.SqlTypes.SqlString
türünde tek bir bağımsız değişkene sahiptir ve X ve Y değerlerinin virgülle ayrılmış dize olarak sağlandığını varsayar.
Microsoft.SqlServer.Server.SqlMethodAttribute.OnNullCall
özniteliğini false
olarak ayarlamak, Parse
yönteminin null bir Point örneğinden çağrılmasını engeller.
-
C#
-
Visual Basic .NET
[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;
}
ToString yöntemini uygulama
ToString
yöntemi, Point
UDT'yi bir dize değerine dönüştürür. Bu durumda, Point
türünün Null örneği için "NULL" dizesi döndürülür.
ToString
yöntemi, X ve Y koordinat değerlerinden oluşan virgülle ayrılmış bir System.String
döndürmek için System.Text.StringBuilder
kullanarak Parse
yöntemini tersine çevirir.
InvokeIfReceiverIsNull
varsayılan değeri false olduğundan, Point
null örneğini denetlemek gereksizdir.
-
C#
-
Visual Basic .NET
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();
}
}
UDT özelliklerini kullanıma sunma
Point
UDT, System.Int32
türünde genel okuma-yazma özellikleri olarak uygulanan X ve Y koordinatlarını kullanıma sunar.
-
C#
-
Visual Basic .NET
public Int32 X
{
get
{
return this._x;
}
set
{
_x = value;
}
}
public Int32 Y
{
get
{
return this._y;
}
set
{
_y = value;
}
}
UDT değerlerini doğrulama
UDT verileriyle çalışırken, SQL Server Veritabanı Altyapısı ikili değerleri otomatik olarak UDT değerlerine dönüştürür. Bu dönüştürme işlemi, değerlerin türün serileştirme biçimine uygun olup olmadığını denetlemeyi ve değerin doğru seri durumdan çıkarılabilmesini sağlar. Bu, değerin ikili forma geri dönüştürülebilmesini sağlar. Bayt sıralı UDF'ler söz konusu olduğunda, sonuçta elde edilen ikili değerin özgün ikili değerle eşleşmesini de sağlar. Bu, geçersiz değerlerin veritabanında kalıcı olmasını engeller. Bazı durumlarda bu denetim düzeyi yetersiz olabilir. UDT değerlerinin beklenen bir etki alanında veya aralıkta olması gerektiğinde ek doğrulama gerekebilir. Örneğin, tarih uygulayan bir UDT, gün değerinin belirli bir geçerli değer aralığı içinde yer alan pozitif bir sayı olmasını gerektirebilir.
Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute
Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.ValidationMethodName
özelliği, veriler UDT'ye atandığında veya UDT'ye dönüştürüldüğünde sunucunun çalıştırdığı bir doğrulama yönteminin adını sağlamanıza olanak tanır.
ValidationMethodName
, bcp yardımcı programı, BULK INSERT
, DBCC CHECKDB
, DBCC CHECKFILEGROUP
, DBCC CHECKTABLE
, dağıtılmış sorgu ve tablosal veri akışı (TDS) uzaktan yordam çağrısı (RPC) işlemleri çalıştırılırken de çağrılır.
ValidationMethodName
için varsayılan değer null değeridir ve doğrulama yöntemi olmadığını belirtir.
Örnek
Aşağıdaki kod parçası, ValidatePoint
ValidationMethodName
belirten Point
sınıfının bildirimini gösterir.
-
C#
-
Visual Basic .NET
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native,
IsByteOrdered=true,
ValidationMethodName = "ValidatePoint")]
public struct Point : INullable { ... }
Bir doğrulama yöntemi belirtilirse, aşağıdaki kod parçasına benzeyen bir imzaya sahip olmalıdır.
-
C#
-
Visual Basic .NET
private bool ValidationFunction()
{
if (validation logic here)
{
return true;
}
else
{
return false;
}
}
Doğrulama yöntemi herhangi bir kapsama sahip olabilir ve değer geçerliyse true
döndürmelidir ve aksi takdirde false
. Yöntem false
döndürürse veya bir özel durum oluşturursa, değer geçerli değil olarak değerlendirilir ve bir hata oluşur.
Aşağıdaki örnekte kod yalnızca X ve Y koordinatlarının sıfır veya daha büyük değerlerine izin verir.
-
C#
-
Visual Basic .NET
private bool ValidatePoint()
{
if ((_x >= 0) && (_y >= 0))
{
return true;
}
else
{
return false;
}
}
Doğrulama yöntemi sınırlamaları
Sunucu, tek tek özellikler ayarlanarak veri eklendiğinde veya veriler bir Transact-SQL INSERT
deyimi kullanılarak eklendiğinde değil, dönüştürme gerçekleştirirken doğrulama yöntemini çağırır.
Doğrulama yönteminin her durumda yürütülmesini istiyorsanız, özellik ayarlayıcılarından doğrulama yöntemini ve Parse
yöntemini açıkça çağırmanız gerekir. Bu bir gereksinim değildir ve bazı durumlarda istenmeyebilir.
Doğrulamayı ayrıştırma örneği
ValidatePoint
yönteminin Point
sınıfında çağrıldığından emin olmak için, Parse
yönteminden ve X ve Y koordinat değerlerini ayarlayan özellik yordamlarından çağırmalısınız. Aşağıdaki kod parçası, Parse
işlevinden ValidatePoint
doğrulama yöntemini çağırmayı gösterir.
-
C#
-
Visual Basic .NET
[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;
}
Özellik doğrulama örneği
Aşağıdaki kod parçası, X ve Y koordinatlarını ayarlayan özellik yordamlarından ValidatePoint
doğrulama yönteminin nasıl çağrıldığını gösterir.
-
C#
-
Visual Basic .NET
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.");
}
}
}
Kod UDT yöntemleri
UDT yöntemlerini kodlarken, kullanılan algoritmanın zaman içinde değişip değişemeyeceğini göz önünde bulundurun. Öyleyse, UDT'nizin kullandığı yöntemler için ayrı bir sınıf oluşturmayı düşünebilirsiniz. Algoritma değişirse sınıfı yeni kodla yeniden derleyebilir ve UDT'yi etkilemeden derlemeyi SQL Server'a yükleyebilirsiniz. Çoğu durumda UDF'ler Transact-SQL ALTER ASSEMBLY
deyimi kullanılarak yeniden yüklenebilir, ancak bu durum mevcut verilerle ilgili sorunlara neden olabilir. Örneğin, AdventureWorks2022
örnek veritabanına dahil edilen Currency
UDT, ayrı bir sınıfta uygulanan para birimi değerlerini dönüştürmek için bir ConvertCurrency
işlevi kullanır. Dönüştürme algoritmaları gelecekte öngörülemeyen şekillerde değişebilir veya yeni işlevler gerekebilir.
ConvertCurrency
işlevini Currency
UDT uygulamasından ayırmak, gelecekteki değişiklikleri planlarken daha fazla esneklik sağlar.
Örnek
Point
sınıfı, uzaklığı hesaplamak için üç basit yöntem içerir: Distance
, DistanceFrom
ve DistanceFromXY
. Her biri, Point
'den sıfıra olan uzaklığı, belirtilen noktadan Point
uzaklığı ve belirtilen X ve Y koordinatlarından Point
uzaklığı hesaplayarak bir double
döndürür.
DistanceFromXY
her çağrıyı Distance
ve DistanceFrom
ve her yöntem için farklı bağımsız değişkenlerin nasıl kullanılacağını gösterin.
-
C#
-
Visual Basic .NET
// 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));
}
SqlMethod özniteliklerini kullanma
Microsoft.SqlServer.Server.SqlMethodAttribute
sınıfı, determinizmi belirtmek, null çağrı davranışında ve yöntemin bir mutator olup olmadığını belirtmek için yöntem tanımlarını işaretlemek için kullanılabilecek özel öznitelikler sağlar. Bu özellikler için varsayılan değerler varsayılır ve özel öznitelik yalnızca varsayılan olmayan bir değer gerektiğinde kullanılır.
Not
SqlMethodAttribute
sınıfı SqlFunctionAttribute
sınıfından devralır, bu nedenle SqlMethodAttribute
FillRowMethodName
ve TableDefinition
alanlarını SqlFunctionAttribute
'den devralır. Bu, tablo değerli bir yöntem yazılabileceği anlamına gelir ve bu durum böyle değildir. Yöntemi derler ve derleme dağıtılır, ancak çalışma zamanında şu iletiyle IEnumerable
dönüş türüyle ilgili bir hata oluşur: "Derleme <assembly>
sınıf <class>
yöntem, özellik veya alan <name>
geçersiz dönüş türüne sahip."
Aşağıdaki tabloda, UDT yöntemlerinde kullanılabilecek bazı ilgili Microsoft.SqlServer.Server.SqlMethodAttribute
özellikleri açıklanır ve varsayılan değerleri listelenir.
Mülk | Açıklama |
---|---|
DataAccess |
İşlevin SQL Server'ın yerel örneğinde depolanan kullanıcı verilerine erişim içerip içermediğini gösterir. Varsayılan değer DataAccessKind.None . |
IsDeterministic |
İşlevin aynı giriş değerleri ve aynı veritabanı durumu verilen aynı çıkış değerlerini oluşturup oluşturmadığını gösterir. Varsayılan değer false . |
IsMutator |
Yönteminin UDT örneğinde durum değişikliğine neden olup olmadığını gösterir. Varsayılan değer false . |
IsPrecise |
İşlevin kayan nokta işlemleri gibi kesin olmayan hesaplamalar içerip içermediğini gösterir. Varsayılan değer false . |
OnNullCall |
Null başvuru giriş bağımsız değişkenleri belirtildiğinde yöntemin çağrılıp çağrılmayacağını gösterir. Varsayılan değer true . |
Örnek
Microsoft.SqlServer.Server.SqlMethodAttribute.IsMutator
özelliği, UDT örneğinin durumunda değişikliğe izin veren bir yöntemi işaretlemenize olanak tanır. Transact-SQL, bir UPDATE
deyiminin SET
yan tümcesinde iki UDT özelliği ayarlamanıza izin vermez. Ancak, iki üyeyi değiştiren bir mutator olarak işaretlenmiş bir yönteminiz olabilir.
Not
Sorgularda mutator yöntemlerine izin verilmez. Bunlar yalnızca atama deyimlerinde veya veri değişikliği deyimlerinde çağrılabilir. Mutator olarak işaretlenmiş bir yöntem void
döndürmezse (veya Visual Basic'te Sub
değilse) CREATE TYPE
hatayla başarısız olur.
Aşağıdaki deyim, Rotate
yöntemine sahip bir Triangles
UDT'nin varlığını varsayar. Aşağıdaki Transact-SQL update deyimi Rotate
yöntemini çağırır:
UPDATE Triangles
SET t.RotateY(0.6)
WHERE id = 5;
Rotate
yöntemi, SQL Server'ın yöntemi bir mutator yöntemi olarak işaretlemesi için true
IsMutator
SqlMethod
öznitelik ayarıyla donatılmıştır. Kod ayrıca OnNullCall
false
olarak ayarlar ve giriş parametrelerinden herhangi biri null başvuru ise yöntemin null başvuru (Visual Basic'teNothing
) döndürdüğünü sunucuya gösterir.
-
C#
-
Visual Basic .NET
[SqlMethod(IsMutator = true, OnNullCall = false)]
public void Rotate(double anglex, double angley, double anglez)
{
RotateX(anglex);
RotateY(angley);
RotateZ(anglez);
}
Kullanıcı tanımlı biçime sahip bir UDT uygulama
Kullanıcı tanımlı biçime sahip bir UDT uygularken, UDT verilerini seri hale getirme ve seri durumdan çıkarma işlemlerini gerçekleştirmek için Microsoft.SqlServer.Server.IBinarySerialize
arabirimini uygulayan Read
ve Write
yöntemleri uygulamanız gerekir. ayrıca Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute
MaxByteSize
özelliğini belirtmelisiniz.
Para birimi UDT
Currency
UDT, SQL Server ile yüklenebilen CLR örneklerine dahildir.
Currency
UDT, belirli bir kültürün parasal sistemindeki para miktarının işlenmesini destekler. İki alan tanımlamanız gerekir: CultureInfo
için bir string
, para birimini kimin dağıtıldığını belirten bir string
(örneğin,en-us
) ve CurrencyValue
için bir decimal
, para miktarı.
Karşılaştırmaları gerçekleştirmek için sunucu tarafından kullanılmasa da, Currency
UDT tek bir yöntemi System.IComparable.CompareTo
kullanıma sunan System.IComparable
arabirimini uygular. Bu, kültürler içindeki para birimi değerlerinin doğru bir şekilde karşılaştırılması veya sıralanması istenen durumlarda istemci tarafında kullanılır.
CLR'de çalışan kod, kültürü para birimi değerinden ayrı olarak karşılaştırır. Transact-SQL kodu için aşağıdaki eylemler karşılaştırmayı belirler:
SQL Server'a karşılaştırmalar için diskte kalıcı ikili gösterimi kullanmasını söyleyen
IsByteOrdered
özniteliğini true olarak ayarlayın.UDT'nin diskte nasıl kalıcı olduğunu ve dolayısıyla UDT değerlerinin Transact-SQL işlemleri için nasıl karşılaştırılıp sıralı olduğunu belirlemek için
Currency
UDT içinWrite
yöntemini kullanın.aşağıdaki ikili biçimi kullanarak
Currency
UDT'yi kaydedin:Kültürü, sağ tarafta null karakterlerle doldurma ile 0-19 baytları için UTF-16 ile kodlanmış bir dize olarak kaydedin.
Para biriminin ondalık değerini içermek için 20 ve üzeri baytları kullanın.
Doldurmanın amacı, kültürün para birimi değerinden tamamen ayrıldığından emin olmaktır, böylece bir UDT Transact-SQL kodunda başka bir UDT ile karşılaştırıldığında kültür baytları kültür baytlarıyla karşılaştırılır ve para birimi bayt değerleri para birimi bayt değerleriyle karşılaştırılır.
Para birimi öznitelikleri
Currency
UDT aşağıdaki özniteliklerle tanımlanır.
-
C#
-
Visual Basic .NET
[Serializable]
[SqlUserDefinedType(Format.UserDefined,
IsByteOrdered = true, MaxByteSize = 32)]
[CLSCompliant(false)]
public struct Currency : INullable, IComparable, IBinarySerialize
{ ... }
ibinaryserialize ile okuma ve yazma yöntemleri oluşturma
UserDefined
serileştirme biçimini seçtiğinizde, IBinarySerialize
arabirimini de uygulamanız ve kendi Read
ve Write
yöntemlerinizi oluşturmanız gerekir.
Currency
UDT'den aşağıdaki yordamlar, UDT'den okumak ve UDT'ye yazmak için System.IO.BinaryReader
ve System.IO.BinaryWriter
kullanır.
-
C#
-
Visual Basic .NET
// 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();
}