locked
Implementing data layer with repository pattern RRS feed

  • Question

  • Hi,

    I hope this question belongs to this forum, if not, I apologize.

    I'm trying to create a data layer for my MVVM app and am getting very confused.

    I read tons of articles and watched some videos. Particularly these:

    https://www.youtube.com/watch?v=rtXpYpZdOzM

    http://blog.falafel.com/implement-step-step-generic-repository-pattern-c/

    http://social.technet.microsoft.com/wiki/contents/articles/28209.wpf-entity-framework-mvvm-walk-through-1.aspx

    The first two explain the repository pattern pretty well, but not how it connects to the Entity Framework. The third one explains Entity Framework alone but that made everything even more confusing.

    My end goal is to have my View Model access  a Repository class via methods like GetItems(), GetCustomers, GetCustomerByID(int id), etc...

    Said functions are to access the DB using Entity Framework somehow.

    When I created an ADO.Net Entity Framework, it created some Model classes for me which i'm very confused for their purpose as I already have my Model classes. Should I delete them or are those a different component in the Data Layer?

    In conclusion, I would be glad if you could help me understand the components of the Data Layer and how they should talk to the ViewModel.

    Thanks

    Friday, January 29, 2016 4:14 PM

Answers

  • Please only ask one question per thread...

    >>Do I then create an EmployeeRepository to inherit from GenericDataRepository to put some specific functions like  employeeRepository.GetTopEmployees()

    Yes.

    >>Let's say in your example here...what it IEmployeeRepository and what does it derive from?

    It is an interface that defines methods that are specific to an employee. It extends the generic IGenericDataRepository<Employee> interface.

    >>Why should I do that? Why not just do:

    The first code snippet is an example of dependency injection. This is a topic of its own but in short, you could inject the view model with any repository that implements the (IEmployeeRepository) interface. This for example makes it easy to test the view model class using a different implementation. Please refer to the following links for more information about dependency injection:
    https://en.wikipedia.org/wiki/Dependency_injection
    http://stackoverflow.com/questions/130794/what-is-dependency-injection

    >>If you do give a good explanation for that(i'm sure you will), should I pass it along to the ViewModel from the ViewModelLocator like this: (?)

    You should inject the view model with an instance of an object that implements the interface every time and everywhere you create an instance of, including in a view model locator.

    >>What is this "params Expression...". How do I use it to make a query?

    By using the params keyword, you can specify a method parameter that takes a variable number of arguments: https://msdn.microsoft.com/en-us/library/w5zay9db.aspx

    Func<T, object>> is a delegate that encapsulates a method that has one parameter of type object and returns a value of the type T: https://msdn.microsoft.com/en-us/library/bb549151(v=vs.110).aspx

    There is an example of how to use it in the article:

    IList<Department> departments = repository.GetAll(d => d.Employees); //include related employees

    >>Why is it different from Andy's example where he uses something that resembles TSQL

    It is generic, i.e. it works for different type of entities and not only for customers.


    >>Relating to 3 again with Andy's example, why aren't you using the await and Async?

    Because async/await has nothing to do with the contents of the article. It is about how to implement a generic data access layer, not about how to write asynchronous code.

    This should hopefully answer your questions. Please start a new thread in the EF forum if you have any further EF related questions: https://social.msdn.microsoft.com/Forums/en-US/home?forum=adodotnetentityframework

    Please also remember to close this thread by marking all helpful posts as answer. And please don't ask several questions in the same thread.

    • Marked as answer by Tomer Agmon Tuesday, February 2, 2016 1:02 PM
    Monday, February 1, 2016 7:48 PM

All replies

  • I strongly recommend you use database first and the model classes EF generates for you rather than some other classes.

    Since you obviously only just discovered Entity Framework I think you should take one step at a time.

    You don't need repositories unless your app is going to be a huge enterprise thing.

    It isn't is it?

    Because you're pretty brave if you decided to do something HUGE as your first ef app.

    Did you take a look at my article and samples?

    http://social.technet.microsoft.com/wiki/contents/articles/28209.wpf-entity-framework-mvvm-walk-through-1.aspx

    and

    https://gallery.technet.microsoft.com/WPF-Entity-Framework-MVVM-78cdc204

    The viewmodels get their data using linq.

    For example

            protected async override void GetData()
            {
                ThrobberVisible = Visibility.Visible;
                ObservableCollection<CustomerVM> _customers = new ObservableCollection<CustomerVM>();
    
                var customers = await (from c in db.Customers
                                        orderby c.CustomerName
                                        select c )
                                        .ToListAsync();
                foreach (Customer cust in customers)
                {
                    _customers.Add(new CustomerVM { IsNew = false, TheEntity = cust });
                }
                Customers = _customers;
                RaisePropertyChanged("Customers");
                ThrobberVisible = Visibility.Collapsed;
            }

    Sure you could genericise everything and introduce a repository and dto and....

    I think all that is a bit much for your first app which uses entity framework.

    They're also not really relevant for small to mid size apps.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Friday, January 29, 2016 4:41 PM
  • Yeah it's a bit much, but I still want to do it. 

    My application is not big but I want it to teach me how a big enterprise application should look like.

    I didn't realize you wrote that article :) I'll take a deeper look at that walkthrough.

    Thanks

    Friday, January 29, 2016 5:13 PM
  • Bear in mind that the dbcontext is a repository itself.

    You could put an instance in an IoC container or just as a resource in application.current.resources if you want to share the same instance of dbcontext.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Friday, January 29, 2016 6:31 PM
  • Please refer to my blog post about how to create a generic data access layer using Entity Framework: http://blog.magnusmontin.net/2013/05/30/generic-dal-using-entity-framework/

    It describes an N-tier enterprise architecture where you keep the entity classes in a separate project and the repositories in the data access layer:

    public interface IGenericDataRepository<T> where T : class
        {
            IList<T> GetAll(params Expression<Func<T, object>>[] navigationProperties);
            IList<T> GetList(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties);
            T GetSingle(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties);
            void Add(params T[] items);
            void Update(params T[] items);
            void Remove(params T[] items);
        }
    
    public interface IEmployeeRepository : IGenericDataRepository<Employee>
        {
        }
    

    You could then use these repositories either in your view model classes or in your business or service layer, e.g.:

    public class ViewModel
        {
            private readonly IEmployeeRepository _employeeRepository;
     
            public ViewModel()
            {
                _employeeRepository = new EmployeeRepository();
            }
     
            public ViewModel(IEmployeeRepository employeeRepository)
            {
                _employeeRepository = employeeRepository;
            }
     
            public IList<Employee> GetAllEmployees()
            {
                return _employeeRepository.GetAll();
            }
    }

    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Saturday, January 30, 2016 10:05 AM
  • Ok...first of all, it worked, so awesome! Great post, very informative.

    Now I have tons of questions!

    1. You created IGenericDataRepository and GenericDataRepository to implement it. Do I then create an EmployeeRepository to inherit from GenericDataRepository to put some specific functions like employeeRepository.GetTopEmployees()? Let's say in your example here...what it IEmployeeRepository and what does it derive from?

    public ViewModel(IEmployeeRepository employeeRepository)
            {
                _employeeRepository = employeeRepository;
            }


    2. You demonstrated above that maybe I should give the ViewModel the repository in the constructor like this:

     public ViewModel(IEmployeeRepository employeeRepository)
            {
                _employeeRepository = employeeRepository;
            }

    Why should I do that? Why not just do:

     public ViewModel()
            {
                _employeeRepository = new IEmployeeRepository();
            }

    If you do give a good explanation for that(i'm sure you will), should I pass it along to the ViewModel from the ViewModelLocator like this: (?)

     public static void CreateMainViewModel
            {
                _MainViewModel = new MainViewModel(new IEmployeeRepository());
            }


    3. From your example, I didn't understand what that code does:

    public virtual IList<T> GetAll(params Expression<Func<T, object>>[] navigationProperties)

    What is this "params Expression...". How do I use it to make a query? Why is it different from Andy's example where he uses something that resembles TSQL:

    var customers = await (from c in db.Customers
                                        orderby c.CustomerName
                                        select c )
                                        .ToListAsync()

    I want to make complex queries using JOIN and stuff.

    4. Relating to 3 again with Andy's example, why aren't you using the await and Async?

    Saturday, January 30, 2016 5:57 PM
  • You might find this interesting:

    http://www.thereformedprogrammer.net/is-the-repository-pattern-useful-with-entity-framework-part-2/

    Personally, I think it's a big mistake to lose the ability to use pass through queries from the UI.

    I would go as far to say that IQueryable is a must.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Saturday, January 30, 2016 6:39 PM
  • When I created an ADO.Net Entity Framework, it created some Model classes for me which i'm very confused for their purpose as I already have my Model classes. Should I delete them or are those a different component in the Data Layer?

    In conclusion, I would be glad if you could help me understand the components of the Data Layer and how they should talk to the ViewModel.

    http://blog.sapiensworks.com/post/2012/04/07/Just-Stop-It!-The-Domain-Model-Is-Not-The-Persistence-Model.aspx/

    http://blog.sapiensworks.com/post/2012/11/01/Repository-vs-DAO.aspx/

    Leave the EF entities at the DAL and send the DTO.

    https://en.wikipedia.org/wiki/Data_transfer_object

    https://entitiestodtos.codeplex.com/

    Sunday, January 31, 2016 2:45 AM
  • Please only ask one question per thread...

    >>Do I then create an EmployeeRepository to inherit from GenericDataRepository to put some specific functions like  employeeRepository.GetTopEmployees()

    Yes.

    >>Let's say in your example here...what it IEmployeeRepository and what does it derive from?

    It is an interface that defines methods that are specific to an employee. It extends the generic IGenericDataRepository<Employee> interface.

    >>Why should I do that? Why not just do:

    The first code snippet is an example of dependency injection. This is a topic of its own but in short, you could inject the view model with any repository that implements the (IEmployeeRepository) interface. This for example makes it easy to test the view model class using a different implementation. Please refer to the following links for more information about dependency injection:
    https://en.wikipedia.org/wiki/Dependency_injection
    http://stackoverflow.com/questions/130794/what-is-dependency-injection

    >>If you do give a good explanation for that(i'm sure you will), should I pass it along to the ViewModel from the ViewModelLocator like this: (?)

    You should inject the view model with an instance of an object that implements the interface every time and everywhere you create an instance of, including in a view model locator.

    >>What is this "params Expression...". How do I use it to make a query?

    By using the params keyword, you can specify a method parameter that takes a variable number of arguments: https://msdn.microsoft.com/en-us/library/w5zay9db.aspx

    Func<T, object>> is a delegate that encapsulates a method that has one parameter of type object and returns a value of the type T: https://msdn.microsoft.com/en-us/library/bb549151(v=vs.110).aspx

    There is an example of how to use it in the article:

    IList<Department> departments = repository.GetAll(d => d.Employees); //include related employees

    >>Why is it different from Andy's example where he uses something that resembles TSQL

    It is generic, i.e. it works for different type of entities and not only for customers.


    >>Relating to 3 again with Andy's example, why aren't you using the await and Async?

    Because async/await has nothing to do with the contents of the article. It is about how to implement a generic data access layer, not about how to write asynchronous code.

    This should hopefully answer your questions. Please start a new thread in the EF forum if you have any further EF related questions: https://social.msdn.microsoft.com/Forums/en-US/home?forum=adodotnetentityframework

    Please also remember to close this thread by marking all helpful posts as answer. And please don't ask several questions in the same thread.

    • Marked as answer by Tomer Agmon Tuesday, February 2, 2016 1:02 PM
    Monday, February 1, 2016 7:48 PM