2015-07-08 6 views
1

У меня есть следующая проблема (высокий уровень): My ViewModel имеет некоторые свойства, которые могут быть отредактированы пользователем (в моем представлении). Большинство свойств напрямую привязаны к моей модели Entity Framework. Во многих ситуациях это приводит к тому, что мне приходится отделять мою модель e. г. после сохранения его в базу данных (если я этого не сделаю, и пользователь внесет некоторые изменения в представление, эти изменения будут автоматически отражаться при вызове следующего SaveChanges()). Отключение его, к сожалению, приводит к тому, что все виртуальные свойства становятся нулевыми. Поэтому я должен убедиться, что создаю надлежащие «копии» моего объекта, прежде чем отсоединять его. Это приводит к множеству побочных эффектов.Побочные эффекты, если ViewModel напрямую привязан к Model of Entity Framework


Чтобы дать Вам лучшее понимание моей проблемы некоторые примеры кода (конечно упрощенных):

Моя модель:

public class Child 
{ 
    public int SomeNumber { get; set; } 
    public string SomeText { get; set; } 
    public int MotherId { get; set; } 
    public virtual Mother Mother { get; set; } 
    public virtual ICollection<Sibling> Siblings { get; set; } 
} 

Мой ViewModel:

public class ChildViewModel : ViewModel 
{ 
    private IGenericRepository<Child> _repository; 

    public string SomeText 
    { 
     get { return MyModel.SomeText; } 
     set 
     { 
      MyModel.SomeText = value; 
      RaisePropertyChanged("SomeText"); 
     } 
    } 

    public Mother Mother 
    { 
     get { return MyModel.Mother; } 
     set 
     { 
      MyModel.Mother = value; 
      RaisePropertyChanged("Mother"); 
     } 
    } 

    public void Save() 
    { 
     if (MyModel.Id == 0) 
     { 
      Insert(); 
     } 
     else 
     {     
      Update(); 
     }    
     UnitOfWork.Save(); 
     _repository.Detach(PrimaryModel); 
    } 
} 

Как вы можете увидеть, что свойства ViewModel напрямую привязаны к моей модели EF. В «Сохранить» мне нужно отсоединиться после сохранения. Если я этого не делаю, это приведет к следующей проблеме: пользователь меняет SomeText в представлении, но не сохраняет. Теперь вызывается UnitOfWork.Save(). Измененное значение SomeText случайно сохраняется. Побочным эффектом этого является то, что свойство Mother теперь будет null.

Чтобы избежать этой ситуации, я попытался создать «реальные» копии моего объекта. Поэтому каждая модель должна реализовать метод для копирования своих значений. Это становится сложным и подверженным ошибкам, когда речь идет о сложных объектах. При попытке сохранить «скопированный» объект у меня есть еще больше побочных эффектов, таких как ошибка Attaching an entity of type ... failed because another entity of the same type already has the same primary key value. (особенно с «скопированными» 1: многие и многие: многие объекты).


Резюме:

  • непосредственно связывать модели через ViewModel к представлению ...
  • ... может привести к некоторым побочным эффектам, когда не отделяя его.
  • Отсоединение модели приводит к виртуальным свойствам, которые становятся нулевыми.
  • Чтобы избежать этого, копия объекта может быть создана до отсоединения.
  • Трудно сохранить скопированные объекты, когда они очень сложны (несколько отношений 1: многие и многие: многие).

Это приводит к проблемам, которые облегчают использование (например, «Сохранить набор данных xyz») - по крайней мере, они должны быть легко imo - стоить много времени, а код становится все более сложным.

Как я могу избежать этих подводных камней?

+0

Наше решение состоит в том, что мы используем объекты модели только как чистые DTO. Мы извлекаем их из EF, наполняем наши собственные объекты и не позволяем им уходить. То же самое для сохранения. Создавайте новые DTO, присоединяйте, заполняйте их и сохраняйте. – Andre

+0

Я думал о том же. Для этого потребуется дополнительный уровень (уровень обслуживания или так), который не будет проблемой. – mosquito87

+0

Вы (мы, у меня такая же проблема) также можем оценить карту, которая отображает из ViewModel в Model (перед сохранением). Ты подумал? – bubi

ответ

0

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

Вот пример:

public string SomeText 
{ 
    get { return MyModel.SomeText; } 
    set 
    { 
     MyModel.SomeText = value; 
     RaisePropertyChanged("SomeText"); 
    } 
} 

В коде выше, вы создаете дополнительное свойство в модели представления, вы не нужно делать это. Я предполагаю, что вы привязку к нему так:

<TextBox Text="{Binding SomeText}" ... /> 

Вместо того, чтобы создать эту дополнительную недвижимость, вы должны связываться с модели. Например:

<TextBox Text="{Binding MyModel.SomeText}" ... /> 

Теперь вам больше не придется беспокоиться о том, чтобы отсоединить вашу модель.

+0

Я должен сделать это, потому что сеттер в свойстве моего ViewModel отличается от установщика в Модели. В моей модели ViewModel мне нужно вызвать RaisePropertyChanged, в моей модели этого нет (и есть еще несколько отличий). Далее я не вижу, как это решает все мои проблемы. Точка с отсосом не решена таким образом. – mosquito87