none
Obtener los registros de una tabla como objetos y guardarlos en una lista

    Pregunta

  • Buen dia a todos estoy intentando hacer los siguiente y queria ver si alguien podria orientarme.

    Estoy usando Ado.net para conectar a mysql, (estoy usando el conector de mysql de .net, si es ado.net de todos modos vdd??)

    y mi intención es obtener los registros de una tabla como objetos y estos guardarlos en una lista algo asi:

    List<persona> listPersona = new List<Persona>();

    listPersona.add( objetoObtenido );

    Tambien si quisiera guardar nueva mente la lista o un objeto de esta como puedo guardar el objeto en una tabla??

    Como hago esto con ado.net??

    martes, 27 de marzo de 2012 5:40

Respuestas

  • Yo haría lo siguiente. 4 capas: Entidades, Acceso a datos, Lógica de negocio y Presentación. Pongo las clases en ese orden.


    public class Persona
        {
            int Id { get; set; }
            string Nombre { get; set; }
            string Apellido { get; set; }
            string DNI { get; set; }
    
            public Persona(int id, string nombre, string apellido, string dni)
            {
                this.Id = id;
                this.Nombre = nombre;
                this.Apellido = apellido;
                this.DNI = dni;
            }
        }
    
        public class PersonaDAL
        {
            public Persona GetPersona(int id)
            {
                //aqui conectas a la base de datos, etc....
                //lees de la BD y contruyes el objeto
                SqlDataReader reader = null;
                //....
                return new Persona(
                   id: Convert.ToInt32(reader["Id"].ToString())
                   , nombre: reader["Nombre"].ToString()
                   , apellido: reader["Apellido"].ToString()
                   , dni: reader["DNI"].ToString()
                   );
    
            }
        }
    
        public class PersonaBL
        {       
            public IList<Persona> getPersonas()
            {
                IList<Persona> personas = new List<Persona>();
                PersonaDAL personaDAL = new PersonaDAL();
                personas.Add(personaDAL.GetPersona(1));
                personas.Add(personaDAL.GetPersona(2));
                return personas;
            }
        }
    
        public class Form1 : Form
        {
            IList<Persona> personas;
            public Form1()
            {
                InitializeComponent();            
                PersonaBL personaBL = new PersonaBL();
                personas = personaBL.getPersonas();            
            }
        }

    La capa de entidades se referencia en el resto de capas. La capa de acceso a datos (DAL) solo es accedida por la capa de negocio (BL). La capa de negocio solo es accedida por la capa de Presentación.

    DAL -> BL -> Presentacion.

    Al ejemplo que te pongo solo te queda añadirle en la capa de acceso a datos (la clase de personaDAL) la parte de ADO.NET y como recuperar los datos de base de datos para crear la clase en el constructor. Después en el Form añadirle la lista como datasource del datagridview.

    Un saludo.

    Edito: si tienes tiempo mira un ORM con Entity Framework o NHibernate, que te van a abstraer de la base de datos (cambiando la cadena de conexión puede conectar con MySql, SQL Server, etc.) y te van a ayudar a pasar los datos a entidades.





    • Editado AdrianRodriguez martes, 27 de marzo de 2012 9:19
    • Marcado como respuesta RogelioAE miércoles, 28 de marzo de 2012 3:17
    martes, 27 de marzo de 2012 8:45
  • Usted utiliza un data adapter para llenar un dataset.  No es necesario.  Lo más sencillo es obtener un data reader.  Directamente usando un command, ejecute ExecuteReader().  Esto devuelve el data reader que le comenté.

    Si insiste en usar un dataset, pues también puede, pero su desempeño es más pobre que el de un data reader.


    Jose R. MCP

    • Marcado como respuesta RogelioAE miércoles, 28 de marzo de 2012 3:18
    martes, 27 de marzo de 2012 10:53

Todas las respuestas

  • La creación del objeto es sencillo y algo muy bueno.  Es la base de la programación de capas, específicamente la capa de negocio.

    Para responderle cómo se crea, pues lo mejor es con un ejemplo.  Asumiré que usted obtiene un SqlDataReader a partir de una consulta Select.  Voy a asumir que dicha consulta está devolviendo los datos correspondientes a personas:

    public class Persona
    {
        //Propiedades.  Normalmente la relación de propiedades
        //a campos en la tabla es 1:1.  O sea:  1 propiedad por cada campo.
        public string Nombre { get; set; }
        public string Apellido { get; set; }
        public DateTime? FechaNacimiento { get; set; }
    
        //Lo más sencillo es que la clase Persona exponga un
        //constructor que acepte un SqlDataReader.
        public Persona(SqlDataReader reader)
        {
            Nombre = reader["Nombre"].ToString();
            Apellido = reader["Apellido"].ToString();
            object fechaNacim = reader["FechaNacim"];
            FechaNacimiento = fechaNacim == DBNull.Value ? null : (DateTime)fechaNacim;
        }
        //Agregamos un constructor en blanco para poder crear
        //nuevas personas.
        public Persona() { }
    
        //Finalmente un método para guardar cambios/nuevas personas.
        public void Guardar()
        {
            //Guardar en base de datos.
        }
    }

    Esa sería la clase.  Ahora puede usted proceder a crear su List<Persona> tal y como lo plantea en su pregunta.  El método Guardar() haría la magia de conectar a MySql y correr una instrucción Update o una instrucción Insert, dependiendo de si el objeto Persona fue creado con el constructor que recibe el SqlDataReader o el constructor sin parámetros.


    Jose R. MCP

    martes, 27 de marzo de 2012 6:17
  • Gracias por responder, lo que estaba buscando era como obtener los resultados de la tabla y estos almacenarlos en la lista, o en un array o si debia usar el datareader he ir construyendo los objetos y estoy irlos añadiendo a la lista, o si hay alguna mejor manera de hacerlo.

    martes, 27 de marzo de 2012 6:39
  • Pues lo mejor es un data reader.  Ahora que lo noto, usé el data reader de SQL Server, jeje.  Supongo que el de MySQL se llama MySqlDataReader.

    En fin, volviendo al tema, no estoy seguro de que entiendo su requerimiento.  Dice usted que queire saber cómo obtener los resultados de la tabla.  ¿Está entonces preguntando cómo se accede a una base de datos de MySQL?


    Jose R. MCP

    martes, 27 de marzo de 2012 6:48
  • Gracias, jeje si mas o menos lo que quiero es obtener los resultados pero estos almacenarlos en la lista,

    Por ejemplo asi es como manejaria una consulta.

    MySqlConnection myConnection = new MySqlConnection("Cadena de conexion");
                MySqlDataAdapter myDataAdapter = new MySqlDataAdapter("SELECT nombre AS Nombre, apellido AS Apellido FROM Peronas",myConnection);
                DataSet dataSet = new DataSet();
                try
                {
                    myDataAdapter.Fill(dataSet,"Personas");
                    dgvUnidadesDeMedida.DataSource = dataSet.Tables["Personas"];
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }       

    Yo lo que intento es en lugar de hacer esto:

    dgvUnidadesDeMedida.DataSource = dataSet.Tables["Personas"];

    sea esto:

    dgvUnidadesDeMedida.DataSource = listaPersonas;

    combobox.datasource = listaPersonas;

    martes, 27 de marzo de 2012 6:54
  • Yo haría lo siguiente. 4 capas: Entidades, Acceso a datos, Lógica de negocio y Presentación. Pongo las clases en ese orden.


    public class Persona
        {
            int Id { get; set; }
            string Nombre { get; set; }
            string Apellido { get; set; }
            string DNI { get; set; }
    
            public Persona(int id, string nombre, string apellido, string dni)
            {
                this.Id = id;
                this.Nombre = nombre;
                this.Apellido = apellido;
                this.DNI = dni;
            }
        }
    
        public class PersonaDAL
        {
            public Persona GetPersona(int id)
            {
                //aqui conectas a la base de datos, etc....
                //lees de la BD y contruyes el objeto
                SqlDataReader reader = null;
                //....
                return new Persona(
                   id: Convert.ToInt32(reader["Id"].ToString())
                   , nombre: reader["Nombre"].ToString()
                   , apellido: reader["Apellido"].ToString()
                   , dni: reader["DNI"].ToString()
                   );
    
            }
        }
    
        public class PersonaBL
        {       
            public IList<Persona> getPersonas()
            {
                IList<Persona> personas = new List<Persona>();
                PersonaDAL personaDAL = new PersonaDAL();
                personas.Add(personaDAL.GetPersona(1));
                personas.Add(personaDAL.GetPersona(2));
                return personas;
            }
        }
    
        public class Form1 : Form
        {
            IList<Persona> personas;
            public Form1()
            {
                InitializeComponent();            
                PersonaBL personaBL = new PersonaBL();
                personas = personaBL.getPersonas();            
            }
        }

    La capa de entidades se referencia en el resto de capas. La capa de acceso a datos (DAL) solo es accedida por la capa de negocio (BL). La capa de negocio solo es accedida por la capa de Presentación.

    DAL -> BL -> Presentacion.

    Al ejemplo que te pongo solo te queda añadirle en la capa de acceso a datos (la clase de personaDAL) la parte de ADO.NET y como recuperar los datos de base de datos para crear la clase en el constructor. Después en el Form añadirle la lista como datasource del datagridview.

    Un saludo.

    Edito: si tienes tiempo mira un ORM con Entity Framework o NHibernate, que te van a abstraer de la base de datos (cambiando la cadena de conexión puede conectar con MySql, SQL Server, etc.) y te van a ayudar a pasar los datos a entidades.





    • Editado AdrianRodriguez martes, 27 de marzo de 2012 9:19
    • Marcado como respuesta RogelioAE miércoles, 28 de marzo de 2012 3:17
    martes, 27 de marzo de 2012 8:45
  • Usted utiliza un data adapter para llenar un dataset.  No es necesario.  Lo más sencillo es obtener un data reader.  Directamente usando un command, ejecute ExecuteReader().  Esto devuelve el data reader que le comenté.

    Si insiste en usar un dataset, pues también puede, pero su desempeño es más pobre que el de un data reader.


    Jose R. MCP

    • Marcado como respuesta RogelioAE miércoles, 28 de marzo de 2012 3:18
    martes, 27 de marzo de 2012 10:53
  • Hola Rogelio,

    Haz caso a lo que comenta Jose y olvidate de leer un DataTable para después convertirlo a un List<T>, hazlo directamente con un DataReader que va como 4 veces más rapido:).

    Nota. Jose. Porque pasas a esa clase en el contructor un  SqlDataReader de esa forma tus clases dependen de este y si necesitas llevarlas después a un sitio donde eso no se permite, por ejemplo Windows Phone, que haces.

    Si ya has declarado tus propiedades como public porque no dejas la clase de esta forma.

    public class Persona
    {
        //Propiedades.  Normalmente la relación de propiedades
        //a campos en la tabla es 1:1.  O sea:  1 propiedad por cada campo.
        public string Nombre { get; set; }
        public string Apellido { get; set; }
        public DateTime? FechaNacimiento { get; set; }
    }


    y lees de esta forma.

    List<Persona> Personas =new List<Persona();
    While Reader.Read()
    {
      Personas.Add(new Persona{etc}); 

    Saludos,



    phurtado
    Mi Blog Blog
    Sigueme en Twitter

    martes, 27 de marzo de 2012 12:03
  • Es una posibilidad, Pedro.  Es cierto que la clase sufriría con un constructor recibiendo un data reader, pero lo más normal es tener una capa de datos y cambiar el data reader por un objeto proveedor de valores de la capa de datos y así el objeto es portable.  Me parece que el constructor tomando el data reader es una buena ilustración de cómo hacer las cosas, haciendo claro la salvedad que estamos haciendo en este momento.  Tiene usted razón en que no es lo ideal, pero suelo tener constructores diferentes para saber qué objetos son nuevos y qué objetos no.  En este ejemplo olvidé esta parte.  Debí agregar una propiedad ID de sólo lectura.  El constructor con el data reader podrá dar un valor a ID mientras que el otro no (y el ID será cero).  Así cuando se llame a Guardar(), el objeto sabrá si es un objeto nuevo (y por lo tanto ocupa realizar un Insert) o si es un objeto viejo (y lo que ocupa hacer es un Update).

    Pero en fin, Pedro, es cierto que el SqlDataReader (o cualquier otro data reader) no es la mejor opción para el constructor.  Lo hice ilustrativamente pensando en que no debía agobiar al usuario con la capa de datos y evitar que eso se interpusiera en la explicación del punto que el OP quiere entender en estos momentos.  Excelente observación de todas formas.


    Jose R. MCP

    martes, 27 de marzo de 2012 12:59
  • Hola,

    Jose  coincido con eso y lo comente por aquello de evitar malas prácticas y sobre todo por parte nuestra.

    Gracias por "Excelente observación" y como observe otra que da para una historia y no pequeña me he tomado la libertad de escribir un post al respecto, espero que os guste.

    La historia interminable 

    Por cierto tu cuando empiezas que como me dijo a mí Don Lluis tienes para escribir y no poco :)

    Saludos,


    phurtado
    Mi Blog Blog
    Sigueme en Twitter

    martes, 27 de marzo de 2012 14:25
  • Muchas gracias a todos por sus respuestas, todas me ayudaron mucho, ahora queda estudiar, gracias.
    miércoles, 28 de marzo de 2012 3:18
  • Gracias por la informacion:

    Si insiste en usar un dataset, pues también puede, pero su desempeño es más pobre que el de un data reader.

    Esto me sirve mmucho lo hare asi y despues usare un ORM

    miércoles, 28 de marzo de 2012 3:19
  • Hola 

    pero como podría hacer esto almacenar datos desde un gridview

    miércoles, 09 de abril de 2014 22:25