I am doing the samething you are for a lot of different Datatypes... I had to create and override the CSLA SmartDateReader to handle this... It might at first glance seem like a lot of extra work but it works great and in ALL my BO objects I call the same function to load the value regardless of the data type and whether or not is a Nullable Type.
MyBusinessCore.Core.SmartDataReader
In my new object I created a simple function used for all type of data, nullable or not. Here is my function below:
I call is like this:
mUserCreated = .GetValue(
Of Nullable(Of Guid))("UserCreated")or
mIsDeleted = .GetValue(
Of Boolean)("IsDeleted")or
mIsMaleGender = .GetValue(Of Nullable(Of Boolean))("GenderIsMale")
The new function is my overriden SmartDateReader looks like this:
Public
Overridable Shadows Function GetValue(Of T)(ByVal name As String) As T Return GetValue(Of T)(GetOrdinal(name)) End Function Public Overridable Shadows Function GetValue(Of T)(ByVal i As Integer) As T Dim rtn As Object = Nothing Dim typeOfT As Type = GetType(T) '///// IF WE HAVE A [NULL] VALUE COMING OUT OF THE DATABASE ///// If IsDBNull(i) ThenIf typeOfT.IsGenericType Then
Return Nothing 'IF NULLABLE TYPE, RETURN NOTHING FOR ALL FIELDS ElseIf typeOfT Is GetType(Boolean) Thenrtn = Convert.ToBoolean(
False) ElseIf typeOfT Is GetType(Byte) Thenrtn = System.Byte.MinValue
ElseIf typeOfT Is GetType(Char) Thenrtn =
Char.MinValue ElseIf typeOfT Is GetType(DateTime) OrElse typeOfT Is GetType(Date) Thenrtn =
Date.MinValue ElseIf typeOfT Is GetType(Decimal) Thenrtn =
Decimal.Zero ElseIf typeOfT Is GetType(Double) Thenrtn = Convert.ToDouble(
0)ElseIf typeOfT Is GetType(Guid) Then
rtn = System.Guid.Empty
ElseIf typeOfT Is GetType(Int16) Thenrtn = Convert.ToInt16(
0) ElseIf typeOfT Is GetType(Int32) Thenrtn = Convert.ToInt32(
0) ElseIf typeOfT Is GetType(Int64) Thenrtn = Convert.ToInt64(
0)ElseIf typeOfT Is GetType(UInt16) Then
rtn = Convert.ToUInt16(
0) ElseIf typeOfT Is GetType(UInt32) Thenrtn = Convert.ToUInt32(
0) ElseIf typeOfT Is GetType(UInt64) Thenrtn = Convert.ToUInt64(
0) ElseIf typeOfT Is GetType(String) Thenrtn =
Nothing Else Throw New NotSupportedException("The data type: " & typeOfT.Name & " is not supported." & NewLine()& "This method [" & System.Reflection.MethodBase.GetCurrentMethod().Name & "] in object [" & System.Reflection.MethodBase.GetCurrentMethod.ReflectedType.Name & "] is not supported.") End If Return CType(rtn, T) End If '///// VALID DATABASE VALUE COMING OUT OF THE DATABASE ///// '///// SPECIAL DB FIELD CONVERSIONS //// If typeOfT Is GetType(Nullable(Of System.UInt16)) Then If DataReader.GetInt16(i) < 0 Then Return Nothingrtn = Convert.ToUInt16(DataReader.GetInt16(i))
ElseIf typeOfT Is GetType(Nullable(Of UInt32)) Then If DataReader.GetInt32(i) < 0 Then Return Nothingrtn = Convert.ToUInt32(datareader.GetInt32(i))
ElseIf typeOfT Is GetType(Nullable(Of UInt64)) Then If DataReader.GetInt64(i) < 0 Then Return Nothingrtn = Convert.ToUInt64(DataReader.GetInt64(i))
ElseIf typeOfT Is GetType(UInt16) Thenrtn = Misc.Strings.IIF(
Of UInt16)(DataReader.GetInt16(i) < 0, Convert.ToUInt16(0), Convert.ToUInt16(DataReader.GetInt16(i))) ElseIf typeOfT Is GetType(UInt32) Thenrtn = Misc.Strings.IIF(
Of UInt32)(DataReader.GetInt32(i) < 0, Convert.ToUInt32(0), Convert.ToUInt32(DataReader.GetInt32(i))) ElseIf typeOfT Is GetType(UInt64) Thenrtn = Misc.Strings.IIF(
Of UInt64)(DataReader.GetInt64(i) < 0, Convert.ToUInt64(0), Convert.ToUInt64(DataReader.GetInt64(i))) Elsertn = GetValue(i)
End If Try Return CType(rtn, T) Catch ex As Exception Throw New InvalidCastException("The data type: " & typeOfT.Name & " will not cast from the database value: " & GetDataTypeName(i) & "[" & GetFieldType(i).Name & "]." & NewLine() & "This method [" & System.Reflection.MethodBase.GetCurrentMethod().Name & "] in object [" & System.Reflection.MethodBase.GetCurrentMethod.ReflectedType.Name & "] is not supported.") End Try End FunctionThis is the sort of code I use with NULLs
Private mRatingViewings As Nullable(Of Int16) = Nothing
Public Property RatingViewings() As Nullable(Of Int16)
Get
CanReadProperty("RatingViewings", True)
Return mRatingViewings
End Get
Set(ByVal value As Nullable(Of Int16))
CanWriteProperty("RatingViewings", True)
If mRatingViewings.HasValue <> value.HasValue OrElse _
(mRatingViewings.HasValue AndAlso value.HasValue AndAlso
mRatingViewings.Value <> value.Value) Then
mRatingViewings = value
PropertyHasChanged("RatingViewings")
End If
End Set
End Property
DataPortal_Fetch:
If Not dr.IsDBNull("RatingViewings") Then mRatingViewings = dr.GetInt16("RatingViewings")
DoInsertUpdate:
cmd.Parameters.AddWithValue("@RatingViewings", IIf(Not mRatingViewings.HasValue, DBNull.Value, mRatingViewings))
I am hoping to build this as an option into CSALGen at some time as I use frequently use NULLs in the database
Bill
Hey Bill...
You may know this already... but i found out that if your SP has a default value already set (i.e. @RatingViewings as smallint = null)
then you can skip the IIF check:
cmd.Parameters.AddWithValue("@RatingViewings", mRatingViewings)
just a thought... i did it the same thing for the longest time but discovered you didn't have to if a Default Value was established.
ward0093
oops... obviously, only with Nullable Values (i.e. Private mRatingViewings as Nullable(of int16) = nothing)
ward0093
Thanks ward I'll give that a try.
Bill
Copyright (c) Marimer LLC