vulkanino
vulkanino

Reputation: 9134

ado.NET getting fields from a datareader by field AND table name

I only use stored procedures to do any operation on the db. I don't want to use an ORB, before you say that :)

For each table I have a corresponding DAO class (VB or C#) for example:

Namespace Dao

    Public Class Client

        Public Sub New(ByVal id As Integer, ByVal description As String)
            Me.id = id
            Me.description = description
        End Sub

        Property id As Integer
        Property description As String
     End Class

End Namespace

The constructor builds the class fields/properties. In another class I usually build a list (container) of my DAO class, calling a SELECT stored procedure, and getting the fields and building the single DAOs:

Public Shared Function GetList() As List(Of Dao.Client)

    Dim model As New List(Of Dao.Client)

    Using dr As MySqlDataReader = DBUtils.CallReadingStoredProcedure("sp_get_clients")

        While dr.Read
            Dim client As New Dao.Client(dr.GetInt32(0), dr.GetString(1))
            model.Add(client)
        End While

        Return model
    End Using

End Function

Sometimes I need to create the same Dao.class from another method. If the fields to build it are many, it would be useful, instead of directly passing the values to the DAO.class constructor - which is error prone - to just pass the data reader to a different constructor, that extracts the fields and builds itself.

It's like passing the construction responsibility into the Dao.class itself:

Namespace Dao

    Public Class Client

        Public Sub New(ByVal dr As DataReader)

            Me.id = dr.GetInt32("id")
            Me.marca_id = dr.GetInt32("marca_id")
            Me.categoria_id = dr.GetInt32("categoria_id")
            Me.codice = dr.GetString("codice")
            Me.descrizione = dr.GetString("descrizione")
            ... many other

        End Sub
...
    End Class

End Namespace

This way even if I use different stored procedures to get the Clients, I use the same code to build them.

It works as long as the datareader fields, that is the SELECT fields, are always named the same. This is possible, but when I have a JOIN, the named fields don't contain the table name, ie with this query in a SP:

SELECT
        OA.id,              -- 0
        OA.articolo_id,         -- 1
        OA.quantita,            -- 2
        OA.quantita_evasa,      -- 3
        OA.prezzo,          -- 4
        A.id,               -- 5
        A.marca_id,         -- 6
        A.categoria_id,         -- 7
        A.codice,           -- 8
        A.descrizione,          -- 9
        A.prezzo_listino,       -- 10
        A.sconto,           -- 11
        A.prezzo_speciale,      -- 12
        A.ha_matricola,         -- 13
        A.unita_misura,         -- 14
        A.peso,             -- 15
        A.codice_barre,         -- 16
        other fields ...
    FROM nm_ordini_articoli OA
    JOIN articoli A ON (OA.articolo_id = A.id)
    other JOINs... 

I can't do dr.getInt32("OA.id") because the field name is "id" and the table name is "OA". I could go with indices but this is pure madness, since I should try to use the same indices for the same data in different stored procedures!

Question is: I want a Dao constructor that builds a class giving a datareader; how do I get the named field from a datareader, including the table alias or name? I want to do something like dr.getInt32("real table name", "field name") or dr.getInt32("table.field")

Other advices? Thanks.

Upvotes: 0

Views: 2007

Answers (2)

vulkanino
vulkanino

Reputation: 9134

A smart friend of mine gave me this elegant and simple solution: use field aliases... It works damn well!

SELECT
        OA.id AS ordine_articolo_id, 
        ...

Upvotes: 0

Richard
Richard

Reputation: 109180

Most of the metadata for a query results is available in the DataTable returned by DataReader.GetSchemaTable. The details of the table are provider dependent, for SQL Server it is documented in SqlDataReader.GetSchemaTable including columns ColumnName, BaseColumnName and BaseTableName.

Remember that a returned column might be calculated in the query and not given a name so they could all be null.

Upvotes: 2

Related Questions