viernes, 18 de febrero de 2011

¿DataRow o DataRowView como origen de datos?

Hoy me ha pasado que tenía la necesidad de devolver un DataRow desde un método en vez de un DataTable. El motivo principal es que el método sólo devuelve 1 registro así que pensé que sería mejor devolver un DataRow que un DataTable.

La sorpresa ha aparecido cuando he enlazado a datos un repetidor con éste registro. Para hacerlo tampoco he hecho nada excepcional, simplemente agregar a mi página .aspx un control de origen de datos (en mi caso un ObjectDataSource) y un control Repeater enlazado al ObjectDataSource a través de la propiedad DataSourceID. Pues bien, las expresiones de tipo Eval(“NombreCampo”) han dejado de funcionar con el mensaje de error “DataBinding: 'System.Data.DataRow' no contiene una propiedad con el nombre 'NombreCampo.

Siendo así, me han asaltado automáticamente una las siguientes preguntas:

  • ¿Se puede enlazar un control enlazado a datos con un DataRow?
  • ¿Se puede enlazar un control enlazado a datos con un DataView?

La respuesta no va a ser complicada, pero antes de resolverla simplemente me gustaría apuntalar algunos conceptos que, aunque quizás sean obvios, no quisiera dejar de exponer.

  • Un DataTable no pertenece siempre a un DataSet, luego la propiedad <NuestroDataTable>.DataSet podría ser Nothing.
  • Un DataRow no pertenece siempre a un DataTable, luego la propiedad <NuestroDataRow>.Table podría ser Nothing.
  • Si enlazamos un control enlazado a datos con un DataTable, en realidad el control enlazado a datos, iterará por su vista por defecto, esto es <NuestroDataTable>.DefaultView que devuelve objetos del tipo DataRowView (no DataRow).
  • Se puede navegar desde un DataRowView a su vista con la propiedad DataView, y desde ahí a su DataTable con la propiedad Table y de ahí a su DataSet con la propiedad DataSet.
  • Para enlazar un control de origen de datos (por ejemplo un Repeater) por código, no se puede establecer su propiedad DataSource a un objeto que no implemente IListSource o IEnumerable, luego no se podrá enlazar con un DataRow o un DataRowView.

Los problemas aparecieron justo a propósito de este último punto, porque mi control ObjectDataSource devolvía un DataRow y puesto que el enlace no es por código sino desde el marcado de la página .aspx, la verdad es que inicialmente, el Repeater no se quejaba. De hecho, te confirmo que si es desde el marcado, un DataRow o DataRowView puede ser perfectamente un origen de datos para un control enlazado a datos (otra cosa es que como veremos más adelante un DataRow no es un objeto muy “agradecido” en lo relativo a éste enlace).

Si el enlace es con un DataTable:

Eval("NombreCampo")

Valor

Container

RepeaterItem

Container.DataItem

DataRowView

DataBinder.GetDataItem(Container)

DataRowView

DataBinder.Eval(Container.DataItem, " NombreCampo ")

Valor

DataBinder.Eval(DataBinder.GetDataItem(Container), " NombreCampo ")

Valor


Si el enlace es con un DataRow:

Eval("NombreCampo")

{"DataBinding: 'System.Data.DataRow' no contiene una propiedad con el nombre 'NombreCampo '."}

Container

RepeaterItem

Container.DataItem

DataRow

DataBinder.GetDataItem(Container)

DataRow

DataBinder.Eval(Container.DataItem, "NombreCampo")

{"DataBinding: 'System.Data.DataRow' no contiene una propiedad con el nombre 'NombreCampo '."}

DataBinder.Eval(DataBinder.GetDataItem(Container), "NombreCampo")

{"DataBinding: 'System.Data.DataRow' no contiene una propiedad con el nombre 'NombreCampo'."}

CType(Container.DataItem, Data.DataRow).Item("NombreCampo ")

Valor


Si el enlace es con un DataRowView:

Eval("NombreCampo")

Valor

Container

RepeaterItem

Container.DataItem

DataRowView

DataBinder.GetDataItem(Container)

DataRowView

DataBinder.Eval(Container.DataItem, "NombreCampo")

Valor

DataBinder.Eval(DataBinder.GetDataItem(Container), "NombreCampo")

Valor

CType(Container.DataItem, Data.DataRowView).Item("NombreCampo")

Valor

 
Las conclusiones que extraigo de todo esto son las siguientes:

  • jamás enlazaré un control de origen de datos con un DataRow
  • sólo a veces enlazaré un control de origen de datos con un DataRowView
  • casi siempre enlazaré un control de origen de datos con un DataTable

De todas formas, si te quieres aclarar un poco más con la sintaxis de Container, DataBinder, etc, puedes visitar este otro post en el que se habló sobre ello.

Un saludo!

No hay comentarios:

Publicar un comentario