Common Problem, I think...

C

Chad

I want to create a class which contains a date, integer and string property which all allow a NULL value.

I don't want to store the values in an Object datatype. I prefer more strongly typed data.

I am interested in using SQL data types for my property types, but in our 4-tier app, we have a Data access layer that passes dataset across tiers to the Application layer, which populates the Business object's properties. In the Data layer, we do everything via Stored procedures using SQLData Adapters.

My understanding is that I would need to use the SQLDataReader.GetSqlInt32 and similar methods to covert a normal integer to the SqlInt32 type before I could store a value in the SqlInt32 property, apparently the CTYPE will not work.

If I have a property "MyClass.MyInt32Property" how would I move a constant integer value iof "2" to this property from the GUI layer which normally doesn't have access to database related classes? Apparently, before I use the DataReader class, I must have an open connection as query results via a Command object.

I consider created my own class which mimics the Integer class but allows for NULL values. Too bad I can't seem to inherit from the Integer base class. However, this class is a tad awkward since now I have to refer to its value using the Value Property and in .NET there is no longer a concept of a default property..

Suggestions would be appreciated.
Option Strict On

Option Explicit On

#Region "IntegerNullable Class-Replacement for Integer datatype. Accepts an Integer, DBNULL, or Nothing"

Public Class IntegerNullable: Inherits System.Object

Implements System.Data.SqlTypes.INullable

Private Const mstrReplaceDataType As String = "System.Int32"

Private mobjValue As Object

Public Property Value() As Object

Get
Return mobjValue
End Get

Set(ByVal Value As Object)

If Value Is Nothing Or Value Is System.DBNull.Value Then
mobjValue = System.DBNull.Value
ElseIf Value.GetType.Name.ToUpper = mstrReplaceDataType.ToUpper Then
mobjValue = Value
Else
Throw New Exception(Me.GetType.Name & " type only accepts values of type " & mstrReplaceDataType & ", DBNull, and Nothing")
End If

End Set

End Property

Public Function ToInteger() As Integer

If IsNull Then
Throw New Exception("Value of " & Me.GetType.Name & " object is Nothing or is DBNull. ToInteger method fails")
End If

Return CType(mobjValue, Integer)

End Function

Public ReadOnly Property IsNull() As Boolean Implements System.Data.SqlTypes.INullable.IsNull

Get
Return (mobjValue Is Nothing Or mobjValue Is System.DBNull.Value)
End Get

End Property

End Class

#End Region
 
G

Guest

Chad,

I'm pretty sure that Visual Studio 2005 will add support for nullable value
types.

If this were an important feature for me I would use VS2005 instead of
trying to work around this limitation in current versions of Visual Studio.

Kerry Moorman
 
K

Ken Dopierala Jr.

Hi,

I recommend that you study, study, study. You are very unfamiliar with what you are talking about. But let's get you going. First place the keyword "Default" in front of your Value property and add the argument it requires. This will give you the default property you are looking for. I'm not sure why you thought that wasn't available. Next study the DataReader object. GetSqlInt32 has nothing to do with conversion. The number you are giving it is the index of the column that should already hold an Integer you retrieved through a query. The Integer datatype in all versions of VB.Net has always been a 32bit signed integer. You should have no problem using CInt to convert whatever value you get from a DataReader or DataAdapter. For NULL I would recommend exposing an IsNull property that is boolean. Then test for it before performing operations. That should both reduce the amount of code you need to write by testing after the fact and is intuitive. Or you can create your own function like .NET's IsDBNull(), but it isn't as elegant. First things first though. Study the framework and dig into the object model. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.
I want to create a class which contains a date, integer and string property which all allow a NULL value.

I don't want to store the values in an Object datatype. I prefer more strongly typed data.

I am interested in using SQL data types for my property types, but in our 4-tier app, we have a Data access layer that passes dataset across tiers to the Application layer, which populates the Business object's properties. In the Data layer, we do everything via Stored procedures using SQLData Adapters.

My understanding is that I would need to use the SQLDataReader.GetSqlInt32 and similar methods to covert a normal integer to the SqlInt32 type before I could store a value in the SqlInt32 property, apparently the CTYPE will not work.

If I have a property "MyClass.MyInt32Property" how would I move a constant integer value iof "2" to this property from the GUI layer which normally doesn't have access to database related classes? Apparently, before I use the DataReader class, I must have an open connection as query results via a Command object.

I consider created my own class which mimics the Integer class but allows for NULL values. Too bad I can't seem to inherit from the Integer base class. However, this class is a tad awkward since now I have to refer to its value using the Value Property and in .NET there is no longer a concept of a default property..

Suggestions would be appreciated.
Option Strict On

Option Explicit On

#Region "IntegerNullable Class-Replacement for Integer datatype. Accepts an Integer, DBNULL, or Nothing"

Public Class IntegerNullable: Inherits System.Object

Implements System.Data.SqlTypes.INullable

Private Const mstrReplaceDataType As String = "System.Int32"

Private mobjValue As Object

Public Property Value() As Object

Get
Return mobjValue
End Get

Set(ByVal Value As Object)

If Value Is Nothing Or Value Is System.DBNull.Value Then
mobjValue = System.DBNull.Value
ElseIf Value.GetType.Name.ToUpper = mstrReplaceDataType.ToUpper Then
mobjValue = Value
Else
Throw New Exception(Me.GetType.Name & " type only accepts values of type " & mstrReplaceDataType & ", DBNull, and Nothing")
End If

End Set

End Property

Public Function ToInteger() As Integer

If IsNull Then
Throw New Exception("Value of " & Me.GetType.Name & " object is Nothing or is DBNull. ToInteger method fails")
End If

Return CType(mobjValue, Integer)

End Function

Public ReadOnly Property IsNull() As Boolean Implements System.Data.SqlTypes.INullable.IsNull

Get
Return (mobjValue Is Nothing Or mobjValue Is System.DBNull.Value)
End Get

End Property

End Class

#End Region
 
C

Cor Ligthert [MVP]

Chad,

In addition to Ken

A value is placed on the stack and holds (a) value(s)
An object is placed on the managed heap. If its address to that is null, than it Is Nothing or as you wrote (Null).

I hope that this gives an idea?

Cor
 
C

Chad

When I said that "the Value property on my object cannot be made the default property" I meant that in VB.NET, unlike VB6, you could not have a default property unless the property accepts a parameter.
In the IntergerNullable class I created, the Value property accepted no params. I believe you suggested that it should. I am confused as to what you are trying to accomplish by adding a param.

Secondly, I see you are correct about the SQLDataReader.GetSqlInt32 method, it does accept as its param, the index of the field that you want to get as a SqlInt32 datatype. However, I feel my question remains.

Please consider the example below. I have a class Account, which has three properties, AccountId, AccountMgrId and SupervisorId. The first is a required integer property. The other properties I would like to allow a NULL value or an integer value only. The AccountMgrId property is implemented to use my custom class IntegerNullable, which is a class that I created to "extend" the Integer so it can also accept NULL values. The problem I have with it is that, because unlike the native INTEGER type, it is a true object and it is awkward to refer to the value of an IntegerNullable type by refering to its Value property rather than just the object itself. However, I do not consider this horrible. In fact, I kind of think that Microsft maybe should have implemented Integers as a real object for consistancy, but I suspect there is alot to this subject. Anyway...

The SupervisorID I implemented in the Account class as a SqlInt32 datatype. I can move a value from the SupervisorId database column to this property using this command:

Account.SupervisorId = DataReader.GetSqlInt32(1)

but in the GUI layer, how do I move a value, say the Integer value "2" to the Account.Supervisor property?

As you see below, when I attempt to do this, I get the error 'System.DBNull' cannot be converted to 'System.Data.SqlTypes.SqlInt32'.

I get the same error if I try to use the CTYPE or the CINT functions:

Account.SupervisorId = CInt(2) 'Value of type 'Integer' cannot be converted to 'System.Data.SqlTypes.SqlInt32'.
Account.SupervisorId = CType(2, Integer) 'Value of type 'Integer' cannot be converted to 'System.Data.SqlTypes.SqlInt32'.

Cor wrote:

A value is placed on the stack and holds (a) value(s)
An object is placed on the managed heap. If its address to that is null, than it Is Nothing or as you wrote (Null).

I hope that this gives an idea?

That wasn't enough help for me. Perhaps you can clarify this point for me?

Anyway, I think my IntegerNullable class will work fine, I just think it is a little awkward.

You comments are welcomed.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim Account As New Account(AccountId:=1)
Dim i As Integer

Account.AccountMgrId = New IntegerNullable(2)

If Account.AccountMgrId.IsNull Then
System.Diagnostics.Debug.WriteLine("The Account has no Manager")
Else
System.Diagnostics.Debug.WriteLine("The Manager's ID is " & Account.AccountMgrId.Value)
End If

Dim DataReader As SqlDataReader

Account.SupervisorId = DBNull.Value 'System.DBNull' cannot be converted to 'System.Data.SqlTypes.SqlInt32'.

Account.SupervisorId = 2 'System.DBNull' cannot be converted to 'System.Data.SqlTypes.SqlInt32'.



End Sub


Public Class Account

'An account must have an ID but it may or may not have an Account Manager

Private m_AccountID As Integer
Private m_AccountMgrId As IntegerNullable
Private m_SupervisorId As System.Data.SqlTypes.SqlInt32

Public Sub New(ByVal AccountID As Integer)
m_AccountID = AccountID
m_AccountMgrId = New IntegerNullable
End Sub

Public Property AccountId() As Integer
Get
Return m_AccountID
End Get
Set(ByVal AccountId As Integer)
m_AccountID = AccountId
End Set
End Property

Public Property AccountMgrId() As IntegerNullable
Get
Return m_AccountMgrId
End Get

Set(ByVal AccountMgrId As IntegerNullable)
m_AccountMgrId = AccountMgrId
End Set

End Property

Public Property SupervisorId() As System.Data.SqlTypes.SqlInt32
Get
Return m_SupervisorId
End Get
Set(ByVal Value As System.Data.SqlTypes.SqlInt32)
m_SupervisorId = Value
End Set
End Property
End Class


Option Strict On
Option Explicit On

Public Class IntegerNullable

Inherits System.Object

Implements System.Data.SqlTypes.INullable

Private mintValue As Integer
Private mblnIsNull As Boolean

Public Sub New()
mintValue = Nothing
mblnIsNull = True
End Sub

Public Sub New(ByVal Value As Integer)
mintValue = Value
mblnIsNull = True
End Sub

Public Property Value() As Integer

Get
If mblnIsNull Then
Throw New Exception("Value property is not accessible when isNull is True. Use IsNull property to test before accessing Value property")
End If
Return mintValue
End Get

Set(ByVal Value As Integer)
mintValue = Value
mblnIsNull = False
End Set

End Property

Public ReadOnly Property IsNull() As Boolean Implements System.Data.SqlTypes.INullable.IsNull
Get
Return mblnIsNull
End Get
End Property

Public Sub Nullify()
mblnIsNull = True
mintValue = Nothing
End Sub

End Class
 
K

Ken Dopierala Jr.

Hi Chad,

I would just use the DataReader.GetInt32() function instead of the GetSqlInt32() function. Unless there is something very specific you need out of it. If there is something very specific then change this line:

Account.SupervisorId = CInt(2)

To:

Account.SupervisorId = New SqlInt32(2)

That will allow you to assign a regular integer to a SQL type integer. Note that if you are using these things in large loops I would definitely move to native .Net types like Integer as they are a little over twice as fast. When I build my objects I use native .Net types and when I read from a dataread I just use GetInt32(). You can even use CInt(DataReader("ColumnName")) then also. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.


When I said that "the Value property on my object cannot be made the default property" I meant that in VB.NET, unlike VB6, you could not have a default property unless the property accepts a parameter.
In the IntergerNullable class I created, the Value property accepted no params. I believe you suggested that it should. I am confused as to what you are trying to accomplish by adding a param.

Secondly, I see you are correct about the SQLDataReader.GetSqlInt32 method, it does accept as its param, the index of the field that you want to get as a SqlInt32 datatype. However, I feel my question remains.

Please consider the example below. I have a class Account, which has three properties, AccountId, AccountMgrId and SupervisorId. The first is a required integer property. The other properties I would like to allow a NULL value or an integer value only. The AccountMgrId property is implemented to use my custom class IntegerNullable, which is a class that I created to "extend" the Integer so it can also accept NULL values. The problem I have with it is that, because unlike the native INTEGER type, it is a true object and it is awkward to refer to the value of an IntegerNullable type by refering to its Value property rather than just the object itself. However, I do not consider this horrible. In fact, I kind of think that Microsft maybe should have implemented Integers as a real object for consistancy, but I suspect there is alot to this subject. Anyway...

The SupervisorID I implemented in the Account class as a SqlInt32 datatype. I can move a value from the SupervisorId database column to this property using this command:

Account.SupervisorId = DataReader.GetSqlInt32(1)

but in the GUI layer, how do I move a value, say the Integer value "2" to the Account.Supervisor property?

As you see below, when I attempt to do this, I get the error 'System.DBNull' cannot be converted to 'System.Data.SqlTypes.SqlInt32'.

I get the same error if I try to use the CTYPE or the CINT functions:

Account.SupervisorId = CInt(2) 'Value of type 'Integer' cannot be converted to 'System.Data.SqlTypes.SqlInt32'.
Account.SupervisorId = CType(2, Integer) 'Value of type 'Integer' cannot be converted to 'System.Data.SqlTypes.SqlInt32'.

Cor wrote:

A value is placed on the stack and holds (a) value(s)
An object is placed on the managed heap. If its address to that is null, than it Is Nothing or as you wrote (Null).

I hope that this gives an idea?

That wasn't enough help for me. Perhaps you can clarify this point for me?

Anyway, I think my IntegerNullable class will work fine, I just think it is a little awkward.

You comments are welcomed.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim Account As New Account(AccountId:=1)
Dim i As Integer

Account.AccountMgrId = New IntegerNullable(2)

If Account.AccountMgrId.IsNull Then
System.Diagnostics.Debug.WriteLine("The Account has no Manager")
Else
System.Diagnostics.Debug.WriteLine("The Manager's ID is " & Account.AccountMgrId.Value)
End If

Dim DataReader As SqlDataReader

Account.SupervisorId = DBNull.Value 'System.DBNull' cannot be converted to 'System.Data.SqlTypes.SqlInt32'.

Account.SupervisorId = 2 'System.DBNull' cannot be converted to 'System.Data.SqlTypes.SqlInt32'.



End Sub


Public Class Account

'An account must have an ID but it may or may not have an Account Manager

Private m_AccountID As Integer
Private m_AccountMgrId As IntegerNullable
Private m_SupervisorId As System.Data.SqlTypes.SqlInt32

Public Sub New(ByVal AccountID As Integer)
m_AccountID = AccountID
m_AccountMgrId = New IntegerNullable
End Sub

Public Property AccountId() As Integer
Get
Return m_AccountID
End Get
Set(ByVal AccountId As Integer)
m_AccountID = AccountId
End Set
End Property

Public Property AccountMgrId() As IntegerNullable
Get
Return m_AccountMgrId
End Get

Set(ByVal AccountMgrId As IntegerNullable)
m_AccountMgrId = AccountMgrId
End Set

End Property

Public Property SupervisorId() As System.Data.SqlTypes.SqlInt32
Get
Return m_SupervisorId
End Get
Set(ByVal Value As System.Data.SqlTypes.SqlInt32)
m_SupervisorId = Value
End Set
End Property
End Class


Option Strict On
Option Explicit On

Public Class IntegerNullable

Inherits System.Object

Implements System.Data.SqlTypes.INullable

Private mintValue As Integer
Private mblnIsNull As Boolean

Public Sub New()
mintValue = Nothing
mblnIsNull = True
End Sub

Public Sub New(ByVal Value As Integer)
mintValue = Value
mblnIsNull = True
End Sub

Public Property Value() As Integer

Get
If mblnIsNull Then
Throw New Exception("Value property is not accessible when isNull is True. Use IsNull property to test before accessing Value property")
End If
Return mintValue
End Get

Set(ByVal Value As Integer)
mintValue = Value
mblnIsNull = False
End Set

End Property

Public ReadOnly Property IsNull() As Boolean Implements System.Data.SqlTypes.INullable.IsNull
Get
Return mblnIsNull
End Get
End Property

Public Sub Nullify()
mblnIsNull = True
mintValue = Nothing
End Sub

End Class
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

n-Tier Question 2
Generic Class Of T conversion 2
Q re Extension Methods 1
Raise Event of Class implementing Interface VB.Net 2
Data binding problem 5
Generic Linked List 9
Syncronizing two threads 16
Class problem 1

Top