Entity Framework 5 обновление записи
Я изучал различные методы редактирования / обновления записи в Entity Framework 5 в ASP.NET MVC3 окружающей среды, но до сих пор ни один из них не отметьте все коробки мне нужно. Я объясню, почему.
Я нашел три метода, к которым я упомяну плюсы и минусы:
метод 1-Загрузите исходную запись, обновите каждое свойство
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();
}
плюсы
- можно указать, какие свойства изменить
- представления не должны содержать каждое свойство
минусы
- 2 x запросов на базу данных, чтобы загрузить оригинал, а затем обновить его
Метод 2-Загрузите исходную запись, установите измененные значения
var original = db.Users.Find(updatedUser.UserId);
if (original != null)
{
db.Entry(original).CurrentValues.SetValues(updatedUser);
db.SaveChanges();
}
плюсы
- передаются только измененные свойства база данных
минусы
- представления должны содержать все свойства
- 2 x запросов на базу данных, чтобы загрузить оригинал, а затем обновить его
Метод 3-Прикрепите обновленную запись и установите состояние в EntityState.Изменено
db.Users.Attach(updatedUser);
db.Entry(updatedUser).State = EntityState.Modified;
db.SaveChanges();
плюсы
- 1 x запрос к базе данных обновление
минусы
- не могу указать, какие свойства изменяются
- представления должны содержать все свойства
вопрос
мой вопрос к вам, ребята; есть ли чистый способ, которым я могу достичь этого набора целей?
- можно указать, какие свойства изменяются
- представления не должны содержать все свойства (например, пароль!)
- 1 x запрос на обновление базы данных
Я понимаю, что это довольно незначительная вещь, чтобы указать, но я могу пропустить простое решение этого. Если не метод один будет преобладать ; -)
7 ответов:
вы ищете:
db.Users.Attach(updatedUser); var entry = db.Entry(updatedUser); entry.Property(e => e.Email).IsModified = true; // other changed properties db.SaveChanges();
Мне очень нравится принятый ответ. Я считаю, что есть еще один способ подойти к этому. Предположим, у вас есть очень короткий список свойств, которые вы никогда не захотите включать в представление, поэтому при обновлении сущности они будут опущены. Допустим, что эти два поля пароль и 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();
этот пример позволяет вам по существу оставить свою бизнес-логику в покое после добавления нового поля в таблицу пользователей и в ваше представление.
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();
я добавил дополнительный метод обновления в мой базовый класс репозитория, который похож на метод обновления, созданный с помощью лесов. Вместо того, чтобы установить весь объект в "измененный", он устанавливает набор отдельных свойств. (T-это универсальный параметр класса.)
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; } }
а потом позвонить, например:
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(); }
мне нравится одна поездка в базу данных. Вероятно, лучше сделать это с моделями представления, хотя, чтобы избежать повторения наборов свойств. Я не сделано это еще потому, что я не знаю, как избежать приведения сообщений проверки на моих валидаторах модели представления в мой доменный проект.
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(); } }
добавить в список вариантов. Вы также можете захватить объект из базы данных и использовать инструмент автоматического отображения, например Auto Mapper чтобы обновить части записи, которые вы хотите изменить..
в зависимости от вашего варианта использования применяются все вышеперечисленные решения. Вот как я обычно это делаю, однако:
для кода на стороне сервера (например, пакетный процесс) я обычно загружаю объекты и работаю с динамическими прокси. Обычно в пакетных процессах вам нужно загрузить данные в любом случае во время запуска службы. Я пытаюсь пакетной загрузки данных вместо использования метода find, чтобы сэкономить время. В зависимости от процесса я использую оптимистический или пессимистический контроль параллелизма (я всегда использую оптимистично за исключением параллельных сценариев выполнения, где мне нужно заблокировать некоторые записи с помощью простых операторов sql, это редко, хотя). В зависимости от кода и сценария воздействие может быть уменьшено почти до нуля.
для сценарии на стороне клиента, у вас есть несколько вариантов
использовать модели представления. Модели должны иметь состояние обновления имущества(немодифицированные-вставил-обновил-удалил). Это ответственность клиента, чтобы установить правильное значение для этого столбца в зависимости от действий пользователя (вставка, обновление, удаление). Сервер может либо запросить БД для исходных значений, либо клиент должен отправить исходные значения на сервер вместе с измененными строками. Сервер должен присоединить исходные значения и использовать столбец UpdateStatus для каждой строки, чтобы решить, как обрабатывать новые значения. В этом сценарии я всегда использую оптимистический параллелизм. Это будет делать только инструкции insert-update-delete, а не какие-либо выборки, но для этого может потребоваться какой-то умный код для обхода графика и обновления сущностей (зависит от вашего сценария - приложения). Картограф может помочь, но не обрабатывает логику CRUD
используйте библиотеку, как бриз.js, который скрывает большую часть этой сложности (как описано в 1) и пытается подогнать ее к вашему варианту использования.
надеюсь, это поможет