none
Pasos para hacer un formulario Maestro - Detalle

    Frage

  • Buenas tardes comunidad, estoy intentando hacer un formulario del tipo maestro - detalle y no logro agarrarle la técnica para que me funcione bien.

    Estoy usando VS 2010, C# y EF 4.

    Tengo una tabla de profesionales (maestro) y otra de familiares (detalle).

    El formulario consta de los campos del profesional y una grilla donde están los familiares.

    El problema es al crear un nuevo profesional, ya que no hay ningún ID a los que hagan referencia los familiares, probé guardando primero el profesional y luego agregar los familiares y funciona perfectamente.

    Lo que intente hacer para cuando agrego un nuevo profesional, es que los familiares se guarden dentro del objeto profesional (obProfesional.familiar.Add(obFamiliar);), pero al querer actualizar la grilla de los familiares, con esta consulta:

    var listaFamiliares = from l in obProfesional.familiar select new { Id = l.idFamiliares, l.estado, l.nombreApellido, l.fechaNacimiento };
    dgFamiliares.DataSource = listaFamiliares.ToList();

    Da un error de: "Referencia a objeto no establecida como instancia de un objeto". Supongo que es porque "idFamiliares" es 0 ya que aun no está guardado en la base de datos.

    Lo que necesito es una guía de cómo hacer un formulario maestro - detalle, mas específicamente como agregar detalles cuando se crea un nuevo maestro.

    Desde ya, muchas gracias,

    Mauro.

    Mittwoch, 8. Dezember 2010 21:42

Antworten

Alle Antworten

  • Hola Mauro,

    Yo estoy empezando con EF, y la verdad que de momento no me he enfrentado a formularios maestro-detalle... pero lo que si que he hecho es leer un montón, y encontrar algún que otro enlace interesante.

    Te dejo este, en el que explica (al final) las relaciones 1 a N, con un pequeño ejemplo y todo. A ver si te ayuda.

     

    http://www.codeproject.com/KB/database/IntroEntityFramework3.aspx

     

    Ya me contarás si te ha servido de algo.

    Un saludo!

    Antonio.

    Montag, 13. Dezember 2010 14:43
  • Hola Antonio, gracias por responder!

     

    Estuve viendo muchos ejemplos y todos usan el maestro ya guardado en la base de datos, por lo que ya tiene un ID para el detalle.

    El problema que tengo yo es que no tengo ese ID cuando hago un maestro nuevo, voy a explicarlo con un ejemplo de una persona y sus telefonos asi se entiende mejor:

    Tengo un formulario que tiene unos campos, por ejemplo nombre y edad, por un lado y por el otro, una grilla en donde van los telefonos, con los botones para agregar y modificar y eliminar. Los botones agregar y modificar abren otra ventana en donde estan el campo para escribir el numero de telefono. Con eso tenemos un formulario del tipo maestro detalle.

    El objeto persona tiene los campos "ID", "nombre" y "edad" y el objeto telefono tiene los campos "ID", "numero" y idPersona" y por la relacion, dentro de persona esta la coleccion de telefonos, por ejemplo obPersona.telefonos

    Ahora cuando quiero hacer una nueva persona, me abre el formulario en blanco, con la grilla vacia y el objeto persona vacio, cargo los datos en nombre y edad y apreto en Agregar para que me abra el formulario para escribir un telefono, al aceptar ese formulario, el objeto telefono se agrega a la coleccion del objeto persona (obPersona.telefono.Add(obTelefono)), pero con el ID de telefono en null y al hacer el select para cargar la grilla de telefonos de esta forma:

    var listaTelefonos = from t in obPersona.telefono select new { ID = t.ID, Numero = t.numero };

    Da el error de "Referencia a objeto no establecida como instancia de un objeto.", pero si lo hago asi:

    var listaTelefonos = from t in obPersona.telefono select t;
    No da ese error! y hasta ahi llego con lo que se.

    Espero que se entienda, sino pongo el codigo, pero me parece que se va a complicar mas.

    Donnerstag, 16. Dezember 2010 21:05
  • Hola Mauro,

    Creo que en la primera línea, estas creando un nuevo objeto (select new {...) por eso te da un error de referencia a objeto no establecida. Si embargo, con la segunda estás obteniendo el objeto que ya existe en el objeto Persona. El tema está en que (imagino, no lo he probado) tendrás que grabar primero el objeto Persona en base de datos para poder recuperar el telefono... pero insisto, tendría que probarlo.

    Si no lo ves claro, pon algo de código e intentamos verlo!

    Un saludo, Antonio.

     

    Freitag, 17. Dezember 2010 11:18
  • Hola Antonio, guardando primero la persona funciona perfecto, pero no me parece correcto que el usuario tenga que guardar primero el maestro para luego agregar los detalles, alguna forma tiene que haber para hacerlo bien, pense en usar tablas auxiliares para guardar el detalle mientras el maestro no este guardado, pero pienso que tiene que existir alguna manera de hacerlo bien en objetos.

    La relacion real de maestro-detalle que tengo, es entre un profesional y sus familiares.

    Ahora te muestro el codigo de los formularios:

    Primero el codigo del formulario de profesional

    private void btAgregarFamiliar_Click(object sender, EventArgs e)
     {
      // Aqui se crea el objeto del formulario para agregar familiares
      // El 0 significa que es un nuevo registro, caso contrario se pasa el ID del que se quiere modificar
      // El ref obProfesional es para que el familiar se le agregue al profesional.
      Formularios.frmFamiliar form = new Formularios.frmFamiliar(0, ref obProfesional);
      
      if (form.ShowDialog() == DialogResult.OK)
      {  
      // Si se da Aceptar en el formulario, se actualiza la grilla
      cargarGrillaFamiliares();
      }
     }
    
    private void cargarGrillaFamiliares()
     {
      // Esta es la forma en que no da el error de referencia
      // var listaFamiliares= from l in obProfesional.familiar select l;
      // Y esta es la forma en que lo quiero hacer, pero da el error
      var listaFamiliares = from l in obProfesional.familiar 
       select new { ID = l.idFamiliares, l.estado, l.nombreApellido, l.fechaNacimiento,
       l.estudianteRegular, l.tipoderelacionfamiliar.nombre };
      
      // dgFamiliares es un DataGridView
      dgFamiliares.DataSource = listaFamiliares.ToList();
     }
    
    Ahora el codigo del formulario de familiar:

    private void btAceptar_Click(object sender, EventArgs e)
     {
      if (validarDatos() == true)
      {
      // obFamiliar esta declarado a nivel de formulario
      obFamiliar.nombreApellido = txtNombre.Text;
      obFamiliar.fechaNacimiento = dtpFechaNacimiento.Value.Date;
      obFamiliar.TipoDeRelacionFamiliar_idRelacionFamiliar = (int)cbRelacion.SelectedValue;
      obFamiliar.estudianteRegular = chEstudiante.Checked;
      obFamiliar.estado = chEstado.Checked;
    
      // Esta condicion es verdadera cuando se esta creando un nuevo familiar
      if (obFamiliar.idFamiliares == 0)
      {
       obProfesional.familiar.Add(obFamiliar);
      }
      
      this.DialogResult = DialogResult.OK;
      }
      else
      {
      MessageBox.Show("Se encontraron los siguientes errores:" + mensajeError, "Atención",
      MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
      mensajeError = "";
      }
     }
    

    Eso me parece que es la parte importante del codigo que hay que analizar.

    De verdad agradezco tu tiempo y ayuda!!

     

    Saludos!

    Mauro

    Freitag, 17. Dezember 2010 16:10
  • Hola Mauro,

    A ver si luego genero una estructura similar y lo pruebo.

    Un saludo!
    Antonio.

     

    Montag, 20. Dezember 2010 15:54
  • Muchas gracias Antonio, si necesitas más código, solo dime y lo agrego aquí!!
    Freitag, 24. Dezember 2010 02:04
  • Hola Mauro,

    Perdona que no haya respondido antes, ando un pelín liado con el fin de año y todas estas cosas.
    Voy a ponerme ahora con un ejemplo de Maestro-Detalle, a ver que tal sale, porque buscando por la web, lo único que encuentro son ejemplos de Maestro detalle utilizando BindingSource... y eso a mi no me gusta ni un pelo, la verdad. Te pongo un ejemplo:

    http://msdn.microsoft.com/en-us/data/ff706685.aspx

    A mi no me gustan los BindingSource porque creo que para aplicaciones más o menos profesionales, te quitan el control de los eventos. No digo yo que estén bien montados, pero personalmente me gusta más tocar las tripas a mi manera.

    Bueno, no me enrollo. En cuanto tenga el ejemplo, te voy contando.

    Un saludo!
    Antonio.

     

    Mittwoch, 29. Dezember 2010 10:16
  • No hay problema Antonio, tomate el tiempo necesario!

    Es verdad de eso que dices del BindingSource, todos los ejemplos lo usan y a mí tampoco me gusta que haga todo automático.

    Más o menos el 15 de enero tengo una reunión con un ex profesor que tuve en la universidad que sabe algo de esto, lo que pueda decirme él y con lo tuyo, espero que podamos resolver este problema y que quede un buen ejemplo en internet para los que busquen algo parecido a esto.

    Espero tu respuesta, pero sin apuros!

    Saludos y feliz año nuevo!

    Mauro.

    Mittwoch, 29. Dezember 2010 19:31
  • Hola Mauro,

    Creo que he conseguido (Tengo que probarlo más) un formulario maestro-detalle, pero utilizando entidades STE de Entity Framework. Voy a darle unas vueltas más, para cerciorarme de que todo funciona correctamente y te cuento cómo esta hecho.

    Un saludo!

    Antonio.

    Montag, 3. Januar 2011 15:56
  • Mauro, como estas? Te comento que hace unos meses empezamos a desarrollar usando EF4, y tengo el mismo problema que vos. Por ejemplo, al cargar un empleado, tengo que grabar para luego poder cargar los familiares. Esto se debe a que el empleado no tiene un Id hasta que lo grabes. Por el momento, lo estamos usando de esa manera. Si llego a encontrar como mejorar esto, te lo hago saber. De igual manera, si encontras la forma de solucinar esto, espero t ayuda. Saludos !
    Dienstag, 4. Januar 2011 19:58
  • Hola Antonio,

    Esas son muy buenas noticias!! Solo tengo que investigar un poco del STE. Espero que puedas conseguirlo pronto.

    Saludos!!!

    Mauro.

    Freitag, 7. Januar 2011 17:25
  • Hola rlavisse, todo bien por aca, vos?

    Al no tener el Id del empleado, lo que probé es agregarlo a la lista de familiares del empleado, sin guardarlo en la base de datos aún, de esta manera: obEmpleado.familiar.Add(obFamiliar) y se agrega a la lista, pero da error al momento de intentar mostrarlo en un DataGridView.

    Apenas consiga algo, lo vas a ver aquí.

    Saludos!!

    Freitag, 7. Januar 2011 17:32
  • Hola gente, ya logre unos avances con esto!

    El error de "Referencia a objeto no establecida como instancia de un objeto." que daba al hacer esta consulta para cargar la grilla:

    var listaFamiliares = from l in obProfesional.familiar 
      select new { ID = l.idFamiliares, l.estado, l.nombreApellido, l.fechaNacimiento,
      l.estudianteRegular, l.tipoderelacionfamiliar.nombre };
    dgFamiliares.DataSource = listaFamiliares.ToList();
    

    era porque estaba utilizando un referencia a otra tabla (l.tipoderelacionfamiliar.nombre), y lo que hice fue hacer un join con la otra tabla así:

    var listaFamiliares = from f in obProfesional.familiar 
               join t in obTipoLN.CargarGrilla() 
               on f.TipoDeRelacionFamiliar_idRelacionFamiliar equals t.idRelacionFamiliar 
               select new { ID = f.idFamiliares, Estado = f.estado, Nombre = f.nombreApellido,
               FechaNac = f.fechaNacimiento, EstReg = f.estudianteRegular, Relación = t.nombre };
    dgFamiliares.DataSource = listaFamiliares.ToList();

    y lo muestra perfectamente!

    Ahora tengo que modificar como trabajan los formularios de los detalles para adaptarlos más a objetos.

     

    Saludos!

    • Bearbeitet Mauro Luque Dienstag, 18. Januar 2011 18:59 correciones
    Dienstag, 18. Januar 2011 18:56
  • Hola Mauro!

    Disculpa que no haya respondido nada, estoy superliao en el trabajo. Este fin de semana tengo la inteción de ir contando cómo generar un formulario maestro detalle utilizando STE. En cuanto vaya posteando lo iré contando por aqui.

    Un saludo!

    Antonio.

    Freitag, 21. Januar 2011 12:26
  • Mauro .. si todavia no encontraste una solucion, te comento que tuve el mismo problema que vos. Pero hoy pude solucionarlo. Te dejo un link , donde vas a encontrar un ejemplo super facil y 100 % practico para que veas como hacer un Maestro - Detalle.

    http://icomparable.blogspot.com/2011/01/maestro-detalle-con-el-entity-framework.html

    Saludos !

    • Als Antwort markiert Mauro Luque Montag, 21. Februar 2011 18:45
    Freitag, 11. Februar 2011 13:43
  • Hola rlavisse, gracias por responder, ya habia solucionado el problema agregando el join en la consulta.

    Te comento como resolvi otro problemita que se presento, para modificar o eliminar un detalle, al no tener el id aun, lo que hice fue agregar una especie de numero de control, que es aleatorio y unico dentro de ese detalle, con el fin de utilizarlo para identificar el registro del detalle que esta seleccionado, ya que todos los id son 0 en ese momento.

    Ahora ya avance mucho con la solucion del join que encontre, pero para algun proyecto nuevo que tenga que hacer, voy a tener en cuenta el ejemplo que me diste, muchas gracias!

    Mauro

    Montag, 21. Februar 2011 18:45