none
Self tracking entities. Actualización, mantenimiento de la información y cambio en la propiedad de seguimiento. RRS feed

  • Pregunta

  • Hola a todos.

    Tengo un nuevo problema con las STE. El problema es que tengo una entidad con una serie de propiedades escalares y una que es una colección (un maestro-detalle, vamos). Cuando reclamo esta entidad añado un nuevo item a su propiedad del tipo colección (BindingList<T>)  el objeto principal tiene la propiedad ChangeTracker.State = "Unchanged". El item nuevo añadido a su colección tiene su propiedad ChangeTracker.State = "Added". Hasta aquí lo encuentro correcto. Llamo al método ApplyChanges del ObjecSet y posteriormente a SaveChanges() y me añade el item de la colección a la base de datos sin ningún problema. El problema viene en que yo no quiero que se cierre el formulario de introducción de datos hasta que el usuario así lo decida, por lo que el elemento continúa cargado. Si el usuario vuelve a pulsar sobre el botón "Guardar" me encuentro con que el item añadido anteriomente a la colección continúa manteniendo su propiedad ChangeTracker.State en "Added", por lo que intenta volver a almacenarlo, generando registros duplicados tantas veces como el usuario pulse "Guardar". Ni con Contexto.AcceptAllChanges() ni de ninguna manera consigo que una vez almacenado el item de la colección éste pase a un estado de "Unchanged" o de "Modified" en caso de que se haya modificado.

    Buscando información por la web comentan que en estos casos hay que iterar manualmente los subitems para poner su estado a "Unchanged". ¿Esto es así?, ¿No es un poco más lógico que una vez almacenado un grafo de objetos en la base de datos todos en caso de éxito todos pasen a un estado "Unchanged" automáticamente? ¿Estoy tan liado con esto que no consigo ver la solución por más sencilla que esta sea (espero que sea este el motivo)?

    Espero que podais ayudarme un poco. Gracias a todos y un saludo.

    lunes, 12 de marzo de 2012 16:36

Respuestas

  • Hola, Xavi.

    De escándalo funciona eso. He sobreescrito el método SaveChanges y la verdad, funciona muy bien. Ahora se me presenta otro problema. Cuando cargo la entidad mediante un método Edit() que tiene una propiedad del tipo BindingList<T> y llamo a su método StartTracking(), este inicializa el seguimiento de cámbios del objeto principal, pero no en los objetos hijos. Dichos objetos los modifico desde un Grid (Telerik), por lo que al no tener activo el tracking no me actualiza ningún cámbio en estos. En cambio, subentidades nuevas si que puedo crear. ¿En donde me estoy equivocando ahora? No logro pillarle el tranquillo a esto de las STE...

    Un saludo y muchas gracias por tu ayuda. Me habia empollado una entrada que se llama "working with sets of self-tracking entities" del MSDN y estaba alucinando colores por momentos, ya que crea una serie de métodos extensores, aplicación de patrón visitor y otras cosas que por ahora me quedan grandes. Tu solución la encuentro rápida, comprensible y elegante.

    Un saludo, maestro.

    • Marcado como respuesta vcatala jueves, 22 de marzo de 2012 10:31
    martes, 13 de marzo de 2012 14:47

Todas las respuestas

  • Hola,

    Como bien dices, no es lógico que al hacer un SaveChanges no pase los objetos a Unchanged. No entiendo porque no se hace pero bueno. Yo te propongo dos soluciones. Una es hacer un SaveChanges(false) cada vez que se pulsa Guardar y al cerrar la ventana hacer un ApplyChanges. Esto lo que hace es guardar temporalmente los valores y al final cerrar el proceso (a modo de cerrar la transacción).

    O crear una clase parcial de tu contexto y sobreescribir el método SaveChanges. Te envío un ejemplo

    namespace WpfApplication2
    {
    	public partial class PruebaEntities
    	{
    		public override int SaveChanges(System.Data.Objects.SaveOptions options)
    		{
    			if ((options & System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave) != System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave)
    				return base.SaveChanges(options);
    
    			var addedEntities = (
    				from entry in this.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added)
    				select entry.Entity as IObjectWithChangeTracker
    			).ToList();
    
    			var result = base.SaveChanges(options);
    
    			foreach(var entity in addedEntities)
    				entity.AcceptChanges();
    
    			return result;
    		}
    	}
    }
    

    Cuidado que debe coincidir exactamente el nombre de la clase y el espacio de nombres.

    Espero haberte ayudado

    martes, 13 de marzo de 2012 4:20
  • Hola, Xavi.

    De escándalo funciona eso. He sobreescrito el método SaveChanges y la verdad, funciona muy bien. Ahora se me presenta otro problema. Cuando cargo la entidad mediante un método Edit() que tiene una propiedad del tipo BindingList<T> y llamo a su método StartTracking(), este inicializa el seguimiento de cámbios del objeto principal, pero no en los objetos hijos. Dichos objetos los modifico desde un Grid (Telerik), por lo que al no tener activo el tracking no me actualiza ningún cámbio en estos. En cambio, subentidades nuevas si que puedo crear. ¿En donde me estoy equivocando ahora? No logro pillarle el tranquillo a esto de las STE...

    Un saludo y muchas gracias por tu ayuda. Me habia empollado una entrada que se llama "working with sets of self-tracking entities" del MSDN y estaba alucinando colores por momentos, ya que crea una serie de métodos extensores, aplicación de patrón visitor y otras cosas que por ahora me quedan grandes. Tu solución la encuentro rápida, comprensible y elegante.

    Un saludo, maestro.

    • Marcado como respuesta vcatala jueves, 22 de marzo de 2012 10:31
    martes, 13 de marzo de 2012 14:47