Частичное обновление объектов сущности с помощью EF 4 - PullRequest
0 голосов
/ 03 декабря 2011

Я реализую уровни приложений DAL и BL.Он размещается как служба WCF, а EF 4 используется как ORM.У нас есть уровень безопасности на основе ролей и бизнес-правило, согласно которому только определенная роль может обновлять только часть объекта.

Вот упрощенный пример проблемы:

У нас есть такие DTO:

MainType
{
    public Guid ID { get; set; }
    public String DoctorField1 { get; set; }
    public String DoctorField2 { get; set; }
    public String NurseField1 { get; set; }
    public String NurseField2 { get; set; }
    public DateTime Created {get; set;}
    public DateTime Updated {get; set;}
    public Guid LastUpdateBy {get; set;}

    public List<DetailsType> Details { get; set; }
}

DetailsType
{
    public Guid MainTypeID { get; set; }
    public Guid SomeIdentityID { get; set; }

    public String DoctorDetail { get; set; }
    public String NurseDetail { get; set; }
    public DateTime Created {get; set;}
    public DateTime Updated {get; set;}
    public Guid LastUpdateBy {get; set;}
}

Эти сущности отображаются в соответствующие таблицы БД с теми же полями.

  • Поле идентификатора MainType является первичным ключом;
  • MainTypeID of DetailsType является внешним ключом таблицы MainType.
  • SomeIdentityID для DetailsType - это FK для некоторой другой сущности, которая не важна для этого образца.
  • MainTypeID SomeIdentityID - сложный первичный ключ для таблицы DetailsType.

Iиметь график таких объектов (1 основной и список деталей) и определенную роль пользователя, который выполняет операцию обновления.Моя задача:

  • ЕСЛИ текущий пользователь имеет роль Доктор - обновлять поля Доктора в главном объекте и всех объектах Сведения, вставлять новые объекты сведений.
  • ЕСЛИ текущий пользователь имеет роль Медсестра - обновлятьПоля медсестры в главном объекте и во всех объектах сведений.
  • сохранить текущую дату в поле Обновление
  • сохранить идентификатор текущего пользователя в поле LastUpdateBy
  • не изменять поле «Создано» и любое другое полекоторые не обновляются этой ролью.

Так, например, если у меня есть пользователь с ролью Доктор, я должен сделать следующее:

  • Обновите DoctorField1, DoctorField2, Обновлено, LastUpdateBy вMainObject
  • Обновление DoctorDetail, Обновлено, LastUpdateBy в каждом подробном объекте
  • НЕ модифицируйте другие поля.

В настоящее время у нас есть реализация, которая читает полный график для MainObject,вносит необходимые изменения и сохраняет обратно в БД.Это решение работает слишком медленно, и мне нужно найти способ его улучшить.В настоящее время я четко знаю, как это сделать с помощью RAW SQL, но это будет моим решением, если больше ничего не поможет.

Как я могу заставить Entity Framework обновлять только необходимые поля и игнорировать другие.

У меня есть несколько успешных результатов с методами ApplyOriginalValues ​​и ApplyCurrentValues ​​для полей String.Идея заключалась в том, чтобы назначить некоторое фиктивное значение свойству в обоих объектах, например строку "@ # $% & @ # $% & @ # $% & @ # $% & @ # $% &", а затем EF обрабатывает их какнеизмененные свойства при сохранении изменений.Однако этот прием не работает с логическими значениями, значениями Int32 и десятичными значениями.Я должен использовать простой подход ко всем объектам.

Буду признателен за любые идеи и мысли по поводу этой проблемы.

1 Ответ

1 голос
/ 04 декабря 2011

Если у вас есть такое конкретное требование, вы должны начать с изменения службы WCF, чтобы не принимать поля, которые пользователь не может изменить.Это приводит к двум простым DTO:

public class MainTypeUpdateDto
{    
    public Guid ID { get; set; }
    public String Field1 { get; set; }
    public String Field2 { get; set; }
    public List<DetailsTypeUpdateDto> Details { get; set; }
}

public class DetailsTypeUpdateDto
{
    public Guid MainTypeID { get; set; }
    public Guid SomeIdentityID { get; set; }
    public String Detail { get; set; }
}

Все остальные поля либо не могут быть обновлены, либо должны обрабатываться логикой на стороне вашего сервера.

Теперь, когда вы получаете dtos, вы можете сопоставить их собъекты реальных объектов.На основе роли пользователя вы будете знать, какие поля и детали вы должны установить.У вас есть два варианта, чтобы заставить EF сохранять только те поля, которые вы хотите:

  • Сначала создайте граф объектов с MainType и связанными деталями.Устанавливайте только идентификаторы в этих сущностях и присоединяйте сущность MainType к контексту.После этого установите все обновляемые поля в текущие значения.Не изменяйте состояние какой-либо сущности.
  • Создайте граф объекта с MainType and all related details and set all Ids and all updatable fields. After that attach MainType` сущностью для контекста и установите вручную состояние для каждого измененного свойства (для каждой сущности).

Вам может понадобиться дополнительная логика, если пользователь также может удалить или добавить детали.

...