Pregunta

Tengo el siguiente escenario:

  1. Las entidades se cargan desde la base de datos.
  2. Uno de ellos se presenta al usuario en un formulario (un Control de usuario de WPF) donde el usuario puede editar las propiedades de esa entidad.
  3. El usuario puede decidir aplicar los cambios a la entidad o cancelar la edición.

¿Cómo implementaría algo como esto con EntityFramework?

Mi problema es que, cuando vinculo la IU directamente a las Propiedades de la Entidad, cada cambio se aplica instantáneamente a la entidad. Quiero retrasarlo hasta el momento en que el usuario presione Aceptar y la entidad se haya validado correctamente.

Pensé en cargar las Entidades con No Tracking y llamar a ApplyPropertyChanges después de que la entidad separada haya sido validada, pero no estoy completamente seguro de la forma correcta de hacerlo. . El documento de EntityFramework en MSDN es muy escaso.

Otra forma en la que podría pensar es en Refresh la entidad con StoreWins , pero no me gusta restablecer los cambios en Cancelar en lugar de aplicar los cambios en Ok.

¿Alguien tiene un buen tutorial o muestra?

¿Fue útil?

Solución

Una de las opciones es lo que dijiste al hacer una consulta sin seguimiento.

ctx.Customers.MergeOption = MergeOption.NoTracking;
var customer = ctx.Customers.First(c => c.ID == 232);

Luego, el cliente puede modificar 'cliente' como se requiere en la memoria, y nada sucede realmente en el contexto.

Ahora, cuando realmente desee realizar el cambio, puede hacer esto:

// get the value from the database
var original = ctx.Customers.First(c => c.ID == customer.ID);
// copy values from the changed entity onto the original.
ctx.ApplyPropertyChanges(customer); .
ctx.SaveChanges();

Ahora, si no está cómodo con la consulta por razones de rendimiento o de concurrencia, puede agregar un nuevo método de extensión AttachAsModified (...) a ObjectContext.

que se ve algo como esto:

public static void AttachAsModified<T>(
    this ObjectContext ctx, 
    string entitySet, 
    T entity)
{
    ctx.AttachTo(entitySet, entity);

    ObjectStateEntry entry = 
            ctx.ObjectStateManager.GetObjectStateEntry(entity);

    // get all the property names
    var propertyNames = 
            from s in entry.CurrentValues.DataRecordInfo.FieldMetadata
            select s.FieldType.Name;

    // mark every property as modified    
    foreach(var propertyName in propertyNames)
    {
        entry.SetModifiedProperty(propertyName);
    }
}

Ahora puedes escribir código como este:

ctx.Customers.MergeOption = MergeOption.NoTracking;
var customer = ctx.Customers.First();
// make changes to the customer in the form
ctx.AttachAsModified("Customers", customer);
ctx.SaveChanges();

Y ahora no tiene consultas simultáneas o extrañas.

El único problema ahora es tratar con las propiedades FK. Probablemente debería ver mi índice de consejos para obtener ayuda aquí: http://blogs.msdn.com/alexj/archive/2009/03/26/index-of-tips.aspx

Espero que esto ayude

Alex

Otros consejos

También sugiero IEditableObject, y adicionalmente IDataErrorInfo.

La forma en que lo hago es que, básicamente, tengo un modelo de vista para una entidad que toma la entidad como parámetro de constructor (básicamente un objeto envoltorio).

En BeginEdit, copio las propiedades de la entidad a mi modelo de vista, por lo que si hago CancelEdit, los datos solo se cambian en ViewModel y la Entidad original no ha cambiado. En EndEdit, solo aplico las propiedades de ViewModel a la Entidad nuevamente, o curso solo si la validación ha tenido éxito.

Para la validación utilizo los métodos de IDataErrorInfo. Acabo de implementar IDataErrorInfo.Error para que compruebe cada nombre de propiedad a través de IDataErrorInfo [string columnName] y concatene los posibles mensajes de error. Si está vacío, todo está bien. (No estoy seguro de si el error está destinado a ser usado de esa manera, pero lo hago)

Si tengo otras Entidades adjuntas a mi Entidad original, como las órdenes de los Clientes, las creo como ViewModels anidados en el ViewModel de la Entidad original. El ViewModel original llama a los métodos Begin, Cancel, EndEdit / Error de sus submodelos en sus propias implementaciones de esos métodos.

Es un poco más de trabajo, pero creo que vale la pena porque entre BeginEdit y EndEdit, puedes estar bastante seguro de que nada cambia sin que te des cuenta. Y tener un fragmento de código para las propiedades habilitadas por INotifyPropertyChanged también ayuda mucho.

La forma normal de hacer esto es enlazar a algo que implementa IEditableObject . Si y cómo se ajusta al marco de la entidad, no estoy seguro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top