Reputation: 9134
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
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
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