Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repository Pattern and MVC help

I'm new to C# and ASP.NET MVC and i'm trying to understand the repository pattern. I've read a whole lot of articles, but I just don't understand how to use it. I'm currently using LINQ to SQL to access my SQL Server 2005 database and for testing purposes I created two tables. I have an Employees table and an EmployeeContacts table. The pk of both tables is UserName.

Employees

  • UserName
  • LastName
  • FirstName
  • Position
  • Email
  • Status

  • HireDate

EmployeeContacts

  • UserName
  • Contact1
  • Contact1Phone
  • Contact1Relationship

There is a one to one relationship between the two tables. An employee can be added, updated, and deleted and so can the data in the EmployeeContacts table.

So would I create a base repository to be used by both entities or should I create a repository for each entity separately? If anybody would be willing to show me some code that would be great.

So far, I have this Employee repository. I also have one for EmployeeContacts.

namespace MvcDirectoryLINQ.Models
{
public class EmployeeRepository
{
    private TestDB_DataDataContext db = new TestDB_DataDataContext();
    private UserName u = new UserName(); 

    //
    // Query Methods

    public IQueryable<Employee> FindAllEmployees()
    {
        return db.Employees;
    }

    public IQueryable<Employee> FindRecentEmployees()
    {
        DateTime myDate = DateTime.Today.AddMonths(-6); 

        return from empl in db.Employees
               where empl.HireDate >= myDate
               orderby empl.HireDate 
               select empl;
    }

    public Employee GetEmployee(string UserName)
    {

        return db.Employees.SingleOrDefault(d => d.UserName == UserName);
    }

    //
    // Insert/Delete Methods

    public void Add(Employee employee)
    {

       // get the UserName which is created from the email
        employee.UserName = u.ReturnUserName(employee.Email); 

        //Insert the new employee into the database
        db.Employees.InsertOnSubmit(employee);
        db.EmployeeContacts.InsertOnSubmit(employee.EmployeeContact); 
    }

    public void Delete(Employee employee)
    {
        db.EmployeeContacts.DeleteOnSubmit(employee.EmployeeContact);
        db.Employees.DeleteOnSubmit(employee);
    }

    //
    // Persistence

    public void Save()
    {
        db.SubmitChanges();
    }
}

}

I have a class for an EmployeeFormViewModel:

namespace MvcDirectoryLINQ.Models
{
public class EmployeeFormViewModel
{
    //Properties
    public Employee Employee { get; private set; }
    public EmployeeContact EmployeeContact { get; private set; }


    //Constructor
    public EmployeeFormViewModel(Employee employee, EmployeeContact employeeContact)
    {

        Employee = employee;
        EmployeeContact = employeeContact;


    }
}
}

Code for EmployeeController:

    [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(string UserName, FormCollection formValues)
    {

        Employee employee = employeeRepository.GetEmployee(UserName);

        EmployeeContact employeecontact = employeecontactRepository.GetContact(UserName); 

        try
        {


            UpdateModel(employee);
            UpdateModel(employeecontact);


            employeecontactRepository.Save(); 
            employeeRepository.Save();


            return RedirectToAction("Details", new { UserName = employee.UserName });
        }
        catch
        {

            foreach (var issue in employee.GetRuleViolations())
            {
                ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
            }


            return View(new EmployeeFormViewModel(employee, attendingID)); 
        }

    }

In my View, i inherit from @model MvcDirectoryLINQ.Models.EmployeeFormViewModel. My Employee data saves correctly but the EmployeeContacts don't and I have no idea why.

Am I implementing the repository pattern correctly?

like image 749
MikeB55 Avatar asked Feb 23 '23 21:02

MikeB55


2 Answers

The main goal when using the Repository Pattern (as far as I understand it) is to decouple your application from using a specific Data Access Layer. You haven't done that here because you create I can see that your EmployeeRepository class does not implement an interface. You really want to have something like EmployeeRepository : IEmployeeRepository

Then, in your Controller code, you can pass around an IEmployeeRepository instead of working concretely with your EmployeeRepository. This will give you two benefits:

  • Should you ever need to switch the backend code, you only need to make another class that implements the interface.
  • When you go to test your Controllers, you can pass around a so called mock object that implements the interface instead of hitting the actual database, which slows your tests down and also breaks Unit Testing.

Another thing I noticed is that you spin up a DataContext inside your repository. If you wanted to make changes to multiple different types of objects you would therefore have multiple DataContexts open, which I don't think is what you want, since your changes won't be transactional. You may want to look into the Unit of Work Pattern for a solution.

When learning about a pattern, try to figure out the main benefit first before trying to implement it. In some cases it may not make sense. Please let me know if you would like me to elaborate on anything. Good luck.

like image 142
skaz Avatar answered Mar 01 '23 23:03

skaz


So would I create a base repository to be used by both entities or should I create a repository for each entity separately?

The general rule when using the repository pattern is that there should be one repository class per each primary entity type. Can the EmployeeContacts live independently of any Employee? If so, they should have their own repository. Are them always related to an Employee? If so, manage them by using the Employee repository itself.

like image 37
Konamiman Avatar answered Mar 01 '23 23:03

Konamiman