Каков наилучший способ сохранить исходные свойства объекта, если они не включены в привязку MVC со страницы редактирования? - PullRequest
1 голос
/ 16 ноября 2011

У меня есть представление ASP.NET MVC для редактирования объекта модели. Страница редактирования включает в себя большинство свойств моего объекта, но не все из них - в частности, она не включает поля CreatedOn и CreatedBy, поскольку они устанавливаются при создании (в моем слое обслуживания) и не должны изменяться в будущем. *

Если я не включу эти свойства в качестве скрытых полей, они не будут обнаружены во время привязки и недоступны при сохранении измененного объекта в моем контексте БД EF 4. В действительности при сохранении исходные значения будут перезаписаны нулями (или по умолчанию для некоторых типов).

Я не хочу оставлять их как скрытые поля, потому что это пустая трата байтов, и я не хочу, чтобы эти значения подвергались потенциальной манипуляции.

Есть ли "первоклассный" способ справиться с этой ситуацией? Можно ли указать, что свойство EF Model следует игнорировать, если явно не установлено?

Ответы [ 5 ]

3 голосов
/ 16 ноября 2011

Используйте либо:

public bool SaveRecording(Recording recording)
{
    // Load only the DateTime property, not the full entity
    DateTime oldCreatedOn = db.Recordings
       .Where(r => r.Id == recording.Id)
       .Select(r => r.CreatedOn)
       .SingleOrDefault();

    recording.CreatedOn = oldCreatedOn;

    db.Entry(recording).State = EntityState.Modified;
    db.SaveChanges();

    return true;
}

( Редактировать: Запрос загружает только столбец CreatedOn из базы данных и поэтому дешевле и быстрее, чем загрузка полной сущности. Потому что вам нужно только свойство CreatedOn с использованием Find. ненужные накладные расходы: вы загружаете все свойства, но вам нужно только один из них. Кроме того, полная загрузка сущности с помощью Find и последующее ее отсоединение могут быть сокращены с помощью AsNoTracking : db.Recordings.AsNoTracking().SingleOrDefault(r => r.Id == recording.Id); Это загружает объект, не присоединяя его, поэтому вам не нужно отсоединять объект. Использование AsNoTracking также ускоряет загрузку объекта.)

Редактировать 2

Если вы хотите загрузить более одного свойства из базы данных, вы можете проецировать в анонимный тип:

public bool SaveRecording(Recording recording)
{
    // Load only the needed properties, not the full entity
    var originalData = db.Recordings
       .Where(r => r.Id == recording.Id)
       .Select(r => new
       {
           CreatedOn = r.CreatedOn,
           CreatedBy = r.CreatedBy
           // perhaps more fields...
       })
       .SingleOrDefault();

    recording.CreatedOn = originalData.CreatedOn;
    recording.CreatedBy = originalData.CreatedBy;
    // perhaps more...

    db.Entry(recording).State = EntityState.Modified;
    db.SaveChanges();

    return true;
}

(конец редактирования 2)

Или:

public bool SaveRecording(Recording recording)
{
    Recording oldVersion = db.Recordings.Find(recording.Id);

    recording.CreatedOn = oldVersion.CreatedOn;

    // flag only properties as modified which did really change
    db.Entry(oldVersion).CurrentValues.SetValues(recording);

    db.SaveChanges();

    return true;
}

( Редактировать: Использование CurrentValues.SetValues помечает только измененные свойства, которые действительно были изменены по сравнению с исходным состоянием в базе данных. При вызове SaveChanges EF будет отправлять только свойства, отмеченные как измененные в операторе UPDATE для базы данных. Принимая во внимание установку состояния в Modified flags всех свойств как измененных, независимо от того, действительно ли они изменились или нет. Оператор UPDATE будет более дорогим, потому что он содержит обновление для все столбцы.)

0 голосов
/ 16 ноября 2011

Если вы хотите избежать дополнительных (ненужных) вызовов вашей базы данных перед каждым обновлением, вы можете использовать самопроверяемые сущности или установить StoreGeneratedPattern="Identity" для этих полей в вашей модели сущностей.И да, Identity вводит в заблуждение, но это звучит как настройка, которую вы хотели бы:

Идентичность Значение создается при вставке и остается неизменным при обновлении.*

http://msdn.microsoft.com/en-us/library/system.data.metadata.edm.storegeneratedpattern.aspx

0 голосов
/ 16 ноября 2011

Вы можете реализовать свой собственный механизм связывания моделей, который игнорирует свойства, которые вы не хотите передавать. Начните здесь - http://lostechies.com/jimmybogard/2009/03/18/a-better-model-binder/

0 голосов
/ 16 ноября 2011

Я думаю, что когда вы собираетесь обновить, используйте getById, чтобы получить всю сущность, а затем установить соответствующие свойства, а затем вы можете обновить.Это будет легко, если вы используете какой-то тип сопоставления ( Automapper ) для сопоставления ваших свойств из модели представления с загруженной сущностью из БД.

0 голосов
/ 16 ноября 2011

Если вы не хотите отправлять эти данные клиенту, я не вижу другой возможности, кроме как загрузить оригинал из БД в вашем слое обслуживания, когда вы сохраняете и объединяете эти значения свойств обратно вна обновленный объект.EF никак не может знать, что вы не установили эти значения в NULL и не хотите их сохранять таким образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...