locked
The correct way of using MVVM pattern with Entity Framework as DAL RRS feed

  • Question

  • I know there are similar questions and blogs over the net, but all of them are significantly  different from each other of how they address the problem.

    I want to use Entity Framework as data layer in my project (using repository patter).

    Because I use EF I don't want to move around entities-objects, instead I want to create DTO for every entity and map the properties accordingly (manual mapping - without third party libraries) .

    I am not sure which MVVM portion should use this DAL. (obviously not the VIEW).

    So the question is:

    Where should I use DAL(ALL CRUD methods are implemented IN DAL, e.g. IEnumerable<Student> GetAllStudents  - where Student is an Entity ) and transfer the result to DTOs?

    Some articles I read say that ViewModel should  reference and use the DAL , others say that ViewModel should be only used as wrapper to the model....

     

     

     

     

     

    Monday, August 1, 2011 4:43 PM

Answers

  • Depends on your requirements.

    There's extra coding involved in transforming your data out one layer into a different layer but it allows more precise control and the two are therefore explicitly decoupled.

    If you don't need that control then you don't need to spend that extra effort.

    Say you have a datagrid on a window showing data of type X in your database.

    You could expose an iqueryable or ienumerable<X> straight up from the model into the viewmodel and on to the view.

    Or

    You could have a viewmodel per row, one of whose properties is of type X

    or

    You could have a viewmodel per row with a set or properties of it's own which are pretty much equivalent to X and translate the properties of X into it.

     

    If you just expose an ienumerable<X> then exposing commands from each row of the datagrid is a pain.

    If you have a viewmodel per row then exposing commands per row is easy.

    If you translate your data each way then you have extra work but you can do whatever fancy stuff you like.

    • Marked as answer by Mark arimo Wednesday, August 3, 2011 4:19 PM
    Monday, August 1, 2011 7:44 PM
  • I think you may be overthinking the whole MVVM pattern.  Since you are using a repsoitory, your VM will use it directly to set various properties.  Here is a simple example of using a repository in a VM:

    public class MainWindowVM : INotifyPropertyChanged
     {
      public MainWindowVM()
      {
       var repository = new ModelRepository();
       ModelProperty = repository.GetModel();
       ModelList = new ObservableCollection<Model>(repository.GetModels());
      }
    
      private Model _modelProperty;
      public Model ModelProperty
      {
       get { return _modelProperty; }
       set
       {
        _modelProperty = value;
        OnPropertyChanged("ModelProperty");
       }
      }
    
      private ObservableCollection<Model> _modelList;
      public ObservableCollection<Model> ModelList
      {
       get { return _modelList; }
       set
       {
        _modelList = value;
        OnPropertyChanged("ModelList");
       }
      }  
    
      public event PropertyChangedEventHandler PropertyChanged;
      public void OnPropertyChanged(String propertyName)
      {
       if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
     }
    
     public class Model : INotifyPropertyChanged
     {
      private string _propertyName;
      public string PropertyName
      {
       get { return _propertyName; }
       set
       {
        _propertyName = value;
        OnPropertyChanged("PropertyName");
       }
      }
    
      public event PropertyChangedEventHandler PropertyChanged;
      public void OnPropertyChanged(String propertyName)
      {
       if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
     }
    
     public class ModelRepository
     {
      public Model GetModel()
      {
       return new Model() { PropertyName = "First" };
      }
    
      public IList<Model> GetModels()
      {
       List<Model> models = new List<Model>();
       models.Add(new Model() { PropertyName = "First" });
       models.Add(new Model() { PropertyName = "Second" });
       models.Add(new Model() { PropertyName = "Third" });
       return models;
      }
     }
    
    

    Notice how the VM is simply using the Repository to get it's data.  The same thing will happen for saving and deleting.  A simple call will be made to the repository for those operations.  You also said that you do not want to use EF entities directly.  If this is the case you may want to look into using CSLA.  It is a very feature rich object framework and it's FREE.  Of course it would be another framework you would have to learn, but it gives you things such as dirty checking, authorization, authentication, n-level undo, and all the CRUD stuff.  Keep in mind that it follows the Active Record pattern, so if you don't like active record you may not want to use it.  As always, you could just use your own objects as well.

    • Marked as answer by Mark arimo Wednesday, August 3, 2011 4:19 PM
    Tuesday, August 2, 2011 2:03 PM
  • So to answer your question.  When using EF you have built-in ORMs which are the model.  So really the ViewModels only need to implement ObsservableCollections of the entity types.  Commands can process CRUD stuff, via the appropriate EF ORM calls.
    JP
    • Edited by Mr. Javaman II Wednesday, August 3, 2011 1:48 PM Happy Coding!
    • Marked as answer by Mark arimo Wednesday, August 3, 2011 4:19 PM
    Tuesday, August 2, 2011 10:38 PM

All replies

  • There's some confusion on this because in reality EF can be put into more than one layer.  If you put EF model into the main project layer, then you can simply create a folder named Model and put it there.  If you choose to move EF to WCF, then you have choices.  You can interface directly with the service from the ViewModel (the service being the MODEL).  Or for purists you would still create a MODEL folder allow the Model code to interface to the service and then allow the MODEL to inject business logic.  This would lead to a design of a more generic service which would be ok as well.

    You can also, implement the MODEL in the project and use ASYNC CTP to emulate a 100% asynchronous solution to back end database gets and puts, updates etc.  I don't personally believe that there's any totally right way other than you follow good programming practices.  "Each class responsible for itself" "Loose coupline" "Code Once".. etc.  Those rules lead to patterns and abstractions anyway.


    JP
    Monday, August 1, 2011 5:14 PM
  • So DAL is actually a part of MODEL layer? (therefore  VIEWMODEL can use it)
    Monday, August 1, 2011 5:40 PM
  • In MVVM the Model is the data access layer.  MVVM teaches that the Viewmodel does know the Model.  Many purists will futher classify the two, but to get started that should be sufficient as you can refactor at anytime.  The answer to your question is YES.
    JP
    Monday, August 1, 2011 5:44 PM
  • And what about exposing the Entities directly?

    Should I use DTOs?

    Monday, August 1, 2011 6:25 PM
  • Depends on your requirements.

    There's extra coding involved in transforming your data out one layer into a different layer but it allows more precise control and the two are therefore explicitly decoupled.

    If you don't need that control then you don't need to spend that extra effort.

    Say you have a datagrid on a window showing data of type X in your database.

    You could expose an iqueryable or ienumerable<X> straight up from the model into the viewmodel and on to the view.

    Or

    You could have a viewmodel per row, one of whose properties is of type X

    or

    You could have a viewmodel per row with a set or properties of it's own which are pretty much equivalent to X and translate the properties of X into it.

     

    If you just expose an ienumerable<X> then exposing commands from each row of the datagrid is a pain.

    If you have a viewmodel per row then exposing commands per row is easy.

    If you translate your data each way then you have extra work but you can do whatever fancy stuff you like.

    • Marked as answer by Mark arimo Wednesday, August 3, 2011 4:19 PM
    Monday, August 1, 2011 7:44 PM
  •  Viewmodels typically bind to ObservableCollections of class types.  This means that the model will interface with EF entitiies, but may pass back ObservableCollections<someClass>.  You can still create forms for specific rows and then SaveChanges.  Is that what you mean by expose Entities?


    JP
    Monday, August 1, 2011 7:48 PM
  • Andy,

    To mach the scenarios you've given let's say I want to display a datagrid where each row is a "student" row from the database.

    The Model would be StudentModel.

    The ViewModel  will be StudentListViewModel that StudentListView will bind to.

     

    Therefore StudentListViewModel will have a refernece to DAL to query the database and expose an Observablecollection<StudentModel> property.

    Because DAL returns IEnumerable<Student> (where Student is an entity), it must be "converted" into Observablecollection<StudentModel>.

    I also handle the Icommands sent from View in this Viewmodel.

    As I understand all of the above must be done in the viewmodel.

    In Studentmodel i do some business logic  like validations and etc...

     

    Am I completely wrong with my design?

    Monday, August 1, 2011 8:27 PM
  • I would simply create a StudentView, StudentViewmodel, and StudentModel.  Where you convert to ObservableCollection from IEnumerable is up to you.  Note that the data grid will bind directly to the IEnumeralbe<Student> But you loose collection changed notifications. Student model would implement business rules, it could also do validation but some people do validation in Viewmodel too.  (For example using Data Contracts).

     


    JP
    Tuesday, August 2, 2011 2:51 AM
  • Well if you substitute Student for X in my post, then my advice still stands.

    The simplest approach may not support your requirements, but if your datagrid of students was read only then you don't need no transformation or anything.

    If I needed to have commands fired from buttons or whatever in each row of this datagrid then I'd bind the datagrid to an observablecollection of studentviewmodel which could perhaps include student as a property.

    Tuesday, August 2, 2011 7:52 AM
  • Acoustic guitar & Andy Oneill,

    Binding List of entities is one of my main issues that I would like to solve.

    I don't want to bind EF Entities to the view (implicitly or explicitly) , so I need to transform the student entity into some DTO.

     

    And yes,  I am going to change the data: update,delete, add.

     

    Tuesday, August 2, 2011 1:42 PM
  • I think you may be overthinking the whole MVVM pattern.  Since you are using a repsoitory, your VM will use it directly to set various properties.  Here is a simple example of using a repository in a VM:

    public class MainWindowVM : INotifyPropertyChanged
     {
      public MainWindowVM()
      {
       var repository = new ModelRepository();
       ModelProperty = repository.GetModel();
       ModelList = new ObservableCollection<Model>(repository.GetModels());
      }
    
      private Model _modelProperty;
      public Model ModelProperty
      {
       get { return _modelProperty; }
       set
       {
        _modelProperty = value;
        OnPropertyChanged("ModelProperty");
       }
      }
    
      private ObservableCollection<Model> _modelList;
      public ObservableCollection<Model> ModelList
      {
       get { return _modelList; }
       set
       {
        _modelList = value;
        OnPropertyChanged("ModelList");
       }
      }  
    
      public event PropertyChangedEventHandler PropertyChanged;
      public void OnPropertyChanged(String propertyName)
      {
       if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
     }
    
     public class Model : INotifyPropertyChanged
     {
      private string _propertyName;
      public string PropertyName
      {
       get { return _propertyName; }
       set
       {
        _propertyName = value;
        OnPropertyChanged("PropertyName");
       }
      }
    
      public event PropertyChangedEventHandler PropertyChanged;
      public void OnPropertyChanged(String propertyName)
      {
       if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
     }
    
     public class ModelRepository
     {
      public Model GetModel()
      {
       return new Model() { PropertyName = "First" };
      }
    
      public IList<Model> GetModels()
      {
       List<Model> models = new List<Model>();
       models.Add(new Model() { PropertyName = "First" });
       models.Add(new Model() { PropertyName = "Second" });
       models.Add(new Model() { PropertyName = "Third" });
       return models;
      }
     }
    
    

    Notice how the VM is simply using the Repository to get it's data.  The same thing will happen for saving and deleting.  A simple call will be made to the repository for those operations.  You also said that you do not want to use EF entities directly.  If this is the case you may want to look into using CSLA.  It is a very feature rich object framework and it's FREE.  Of course it would be another framework you would have to learn, but it gives you things such as dirty checking, authorization, authentication, n-level undo, and all the CRUD stuff.  Keep in mind that it follows the Active Record pattern, so if you don't like active record you may not want to use it.  As always, you could just use your own objects as well.

    • Marked as answer by Mark arimo Wednesday, August 3, 2011 4:19 PM
    Tuesday, August 2, 2011 2:03 PM
  • Thanks for  example,

    regarding the framework ,as i said in previous posts, I don't want to use any other framework.

    So I plan to create simple objects for that matter.

    Tuesday, August 2, 2011 2:30 PM
  • So to answer your question.  When using EF you have built-in ORMs which are the model.  So really the ViewModels only need to implement ObsservableCollections of the entity types.  Commands can process CRUD stuff, via the appropriate EF ORM calls.
    JP
    • Edited by Mr. Javaman II Wednesday, August 3, 2011 1:48 PM Happy Coding!
    • Marked as answer by Mark arimo Wednesday, August 3, 2011 4:19 PM
    Tuesday, August 2, 2011 10:38 PM
  • yeah...

    The MVVM + Repository is beautiful but complex if the project is not big :)

    Wednesday, August 3, 2011 4:18 PM