tutorial mvc framework español c# asp.net-mvc-3 entity-framework-5

mvc - entity framework tutorial c# español



Entity Framework 5 Actualizando un Registro (7)

Dependiendo de su caso de uso, se aplican todas las soluciones anteriores. Así es como normalmente lo hago sin embargo:

Para el código del lado del servidor (por ejemplo, un proceso por lotes), por lo general carga las entidades y trabajo con proxies dinámicos. Por lo general, en los procesos por lotes debe cargar los datos de todos modos en el momento en que se ejecuta el servicio. Intento cargar por lotes los datos en lugar de usar el método de búsqueda para ahorrar algo de tiempo. Dependiendo del proceso, uso un control de concurrencia optimista o pesimista (siempre uso el optimismo, excepto en los escenarios de ejecución paralela en los que necesito bloquear algunos registros con sentencias de sql sin formato, aunque esto es raro). Dependiendo del código y el escenario, el impacto se puede reducir a casi cero.

Para los escenarios del lado del cliente, tiene algunas opciones.

  1. Utilizar modelos de vista. Los modelos deben tener una propiedad UpdateStatus (sin modificar-insertada-actualizada-eliminada). Es responsabilidad del cliente establecer el valor correcto en esta columna dependiendo de las acciones del usuario (insertar-actualizar-eliminar). El servidor puede consultar la base de datos para los valores originales o el cliente debe enviar los valores originales al servidor junto con las filas modificadas. El servidor debe adjuntar los valores originales y usar la columna UpdateStatus para cada fila para decidir cómo manejar los nuevos valores. En este escenario siempre uso la concurrencia optimista. Esto solo hará las instrucciones insertar - actualizar - eliminar y no las selecciones, pero podría necesitar algún código inteligente para recorrer el gráfico y actualizar las entidades (depende de su escenario - aplicación). Un mapeador puede ayudar pero no maneja la lógica CRUD

  2. Utilice una biblioteca como breeze.js que oculta la mayor parte de esta complejidad (como se describe en 1) e intente adaptarla a su caso de uso.

Espero eso ayude

He estado explorando diferentes métodos para editar / actualizar un registro dentro de Entity Framework 5 en un entorno ASP.NET MVC3, pero hasta ahora ninguno de ellos marca todos los cuadros que necesito. Voy a explicar por que

He encontrado tres métodos a los que voy a mencionar los pros y los contras:

Método 1 - Cargar registro original, actualizar cada propiedad

var original = db.Users.Find(updatedUser.UserId); if (original != null) { original.BusinessEntityId = updatedUser.BusinessEntityId; original.Email = updatedUser.Email; original.EmployeeId = updatedUser.EmployeeId; original.Forename = updatedUser.Forename; original.Surname = updatedUser.Surname; original.Telephone = updatedUser.Telephone; original.Title = updatedUser.Title; original.Fax = updatedUser.Fax; original.ASPNetUserId = updatedUser.ASPNetUserId; db.SaveChanges(); }

Pros

  • Puede especificar qué propiedades cambian
  • Las vistas no necesitan contener cada propiedad

Contras

  • 2 x consultas en la base de datos para cargar el original y luego actualizarlo

Método 2 - Cargar registro original, establecer valores modificados

var original = db.Users.Find(updatedUser.UserId); if (original != null) { db.Entry(original).CurrentValues.SetValues(updatedUser); db.SaveChanges(); }

Pros

  • Sólo las propiedades modificadas se envían a la base de datos

Contras

  • Las vistas deben contener cada propiedad.
  • 2 x consultas en la base de datos para cargar el original y luego actualizarlo

Método 3: adjunte el registro actualizado y establezca el estado a EntityState.Modified

db.Users.Attach(updatedUser); db.Entry(updatedUser).State = EntityState.Modified; db.SaveChanges();

Pros

  • 1 x consulta en la base de datos para actualizar

Contras

  • No se puede especificar qué propiedades cambian
  • Las vistas deben contener cada propiedad

Pregunta

Mi pregunta para ustedes, chicos; ¿Hay una manera limpia de que pueda lograr este conjunto de objetivos?

  • Puede especificar qué propiedades cambian
  • Las vistas no necesitan contener todas las propiedades (como la contraseña)
  • 1 x consulta en la base de datos para actualizar

Entiendo que esto es una cosa menor que señalar, pero me puede faltar una solución simple para esto. Si no es el método uno prevalecerá ;-)


Estás buscando:

db.Users.Attach(updatedUser); var entry = db.Entry(updatedUser); entry.Property(e => e.Email).IsModified = true; // other changed properties db.SaveChanges();


He agregado un método de actualización adicional a mi clase base de repositorio que es similar al método de actualización generado por Scaffolding. En lugar de configurar todo el objeto a "modificado", establece un conjunto de propiedades individuales. (T es un parámetro genérico de clase).

public void Update(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) { Context.Set<T>().Attach(obj); foreach (var p in propertiesToUpdate) { Context.Entry(obj).Property(p).IsModified = true; } }

Y luego llamar, por ejemplo:

public void UpdatePasswordAndEmail(long userId, string password, string email) { var user = new User {UserId = userId, Password = password, Email = email}; Update(user, u => u.Password, u => u.Email); Save(); }

Me gusta un viaje a la base de datos. Sin embargo, probablemente sea mejor hacer esto con modelos de vista, para evitar la repetición de conjuntos de propiedades. No lo he hecho todavía porque no sé cómo evitar traer los mensajes de validación en mis verificadores de modelo de vista a mi proyecto de dominio.


Realmente me gusta la respuesta aceptada. Creo que hay otra manera de abordar esto también. Supongamos que tiene una lista muy corta de propiedades que no querría incluir en una Vista, por lo que al actualizar la entidad, se omitirán. Digamos que esos dos campos son Contraseña y SSN.

db.Users.Attach(updatedUser); var entry = db.Entry(updatedUser); entry.State = EntityState.Modified; entry.Property(e => e.Password).IsModified = false; entry.Property(e => e.SSN).IsModified = false; db.SaveChanges();

Este ejemplo le permite esencialmente dejar su lógica de negocios solo después de agregar un nuevo campo a su tabla de Usuarios y a su Vista.


Solo para agregar a la lista de opciones. También puede tomar el objeto de la base de datos y usar una herramienta de mapeo automático como Auto Mapper para actualizar las partes del registro que desea cambiar.


foreach(PropertyInfo propertyInfo in original.GetType().GetProperties()) { if (propertyInfo.GetValue(updatedUser, null) == null) propertyInfo.SetValue(updatedUser, propertyInfo.GetValue(original, null), null); } db.Entry(original).CurrentValues.SetValues(updatedUser); db.SaveChanges();


public interface IRepository { void Update<T>(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) where T : class; } public class Repository : DbContext, IRepository { public void Update<T>(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) where T : class { Set<T>().Attach(obj); propertiesToUpdate.ToList().ForEach(p => Entry(obj).Property(p).IsModified = true); SaveChanges(); } }