tags:

views:

179

answers:

2

I have numeric data that I am getting from a database. They are all numeric, but they are a mix of int, money and real.

Using VB.NET, how can you programmatically determine the datatype of a field in a resultset?

A: 

With access to only the underlying value and not the structure of the database, it's not possible to definitively tell what type the value is. The reason why is that there is an overlap in the domain of Money, Real and Int values. The number 4 for example could be both a Real an Int and likely a Money.

Can you give us some more context on the issue? Are you trying to convert a raw database value into a Int style value in VB.Net? Can you show us some code?

JaredPar
I want to format currency as such and leave int as is, and real as a number rounded to 2 decimal positions. The code is this: (all values are coming in as 1 record.)reader = cmd.ExecuteReader()reader.Read()If reader.HasRows Then Me.DataGridView1.Rows.Clear()For i = 0 To reader.FieldCount - 1 Me.DataGridView1.Rows.Add() Me.DataGridView1.Rows(Me.DataGridView1.RowCount - 1).Cells(0).Value = reader.GetName(i).ToString Me.DataGridView1.Rows(Me.DataGridView1.RowCount - 1).Cells(1).Value = reader.Item(i).ToStringNext Me.DataGridView1.Refresh() End If
bochur1
sorry about the code, i posted it readable and site dropped all spaces, etc.
bochur1
@bochur1: Post it in your question.
Jason
+1  A: 

Assuming this table:

CREATE TABLE TestTable
(
Col1 int,
Col2 dec(9,2),
Col3 money
)

With these values:

INSERT INTO TestTable VALUES (1, 2.5, 3.45)

You can use the following code to get the types as .Net types:

    Dim DSN = "SERVER=XYZ;UID=XYZ;PWD=XYZ;DATABASE=XYZ"
    Using Con As New SqlConnection(DSN)
        Con.Open()
        Using Com As New SqlCommand("SELECT * FROM TestTable", Con)
            Com.CommandType = CommandType.Text
            Using RDR = Com.ExecuteReader()
                If RDR.Read Then
                    Trace.WriteLine(RDR.GetProviderSpecificFieldType(0)) 'Returns System.Data.SqlTypes.SqlInt32
                    Trace.WriteLine(RDR.GetProviderSpecificFieldType(1)) 'Returns System.Data.SqlTypes.SqlDecimal
                    Trace.WriteLine(RDR.GetProviderSpecificFieldType(2)) 'Returns System.Data.SqlTypes.SqlMoney
                End If
            End Using
        End Using
        Con.Close()
    End Using

You can also use this to just get the SQL text version of the type:

    Dim DSN = "SERVER=XYZ;UID=XYZ;PWD=XYZ;DATABASE=XYZ"
    Using Con As New SqlConnection(DSN)
        Con.Open()
        Using Com As New SqlCommand("SELECT * FROM TestTable", Con)
            Com.CommandType = CommandType.Text
            Using RDR = Com.ExecuteReader()
                If RDR.Read Then
                    Using SC = RDR.GetSchemaTable()
                        Trace.WriteLine(SC.Rows(0).Item("DataTypeName")) 'Returns int
                        Trace.WriteLine(SC.Rows(1).Item("DataTypeName")) 'Returns decimal
                        Trace.WriteLine(SC.Rows(2).Item("DataTypeName")) 'Returns money
                    End Using
                End If
            End Using
        End Using
        Con.Close()
    End Using

EDIT

Here's how to do type comparison along with a helper function that formats things. Outputs once again assume the above SQL.

    Dim DSN = "SERVER=XYZ;UID=XYZ;PWD=XYZ;DATABASE=XYZ"
    Using Con As New SqlConnection(DSN)
        Con.Open()
        Using Com As New SqlCommand("SELECT * FROM TestTable", Con)
            Com.CommandType = CommandType.Text
            Using RDR = Com.ExecuteReader()
                If RDR.Read Then
                    Trace.WriteLine(FormatNumber(RDR.Item(0), RDR.GetProviderSpecificFieldType(0))) '1
                    Trace.WriteLine(FormatNumber(RDR.Item(1), RDR.GetProviderSpecificFieldType(1))) '2.50
                    Trace.WriteLine(FormatNumber(RDR.Item(2), RDR.GetProviderSpecificFieldType(2))) '$3.45
                End If
            End Using
        End Using
        Con.Close()
    End Using

Private Shared Function FormatNumber(ByVal number As Object, ByVal type As Type) As String
    If number Is Nothing Then Throw New ArgumentNullException("number")
    If type Is Nothing Then Throw New ArgumentNullException("type")
    If type.Equals(GetType(System.Data.SqlTypes.SqlInt32)) Then
        Return Integer.Parse(number)
    ElseIf type.Equals(GetType(System.Data.SqlTypes.SqlDecimal)) Then
        Return Decimal.Parse(number.ToString()).ToString("N")
    ElseIf type.Equals(GetType(System.Data.SqlTypes.SqlMoney)) Then
        Return Decimal.Parse(number.ToString()).ToString("C")
    End If
    Throw New ArgumentOutOfRangeException(String.Format("Unknown type specified : " & type.ToString()))
End Function
Chris Haas
Great info!!!But I am having trouble getting this to work in vb.net.I tried this:If reader.GetProviderSpecificFieldType(i) = System.Data.SqlTypes.SqlMoneyand I get an error saying that the SqlMoney is a Type and cannot be used in an expression.The GetSchemaTable I am having more trouble getting to work since the intelisence is not picking it up.but when I try it in the debugger like:typeof sc.rows(0).Item(0) is int I get false, and I get false no mater what type I try to compare it to. (It is an integer).
bochur1
great!! Thanks!!>Integer.Parse(number)Had to be changed to CsCStr(Integer.Parse(CStr(number)))
bochur1
Sorry, should have been Integer.Parse(number.ToString()).ToString(), looks like I had Option String Off at the time.
Chris Haas
Is .ToString better than using Cstr ?
bochur1
I don't know for sure but I think that CStr actually calls ToString() behind the scenes once it figures out what type it is. ToString() is the ".Net way" and CStr is the "VB" way, neither are right or wrong.
Chris Haas