简体   繁体   English

存储库模式和MVC帮助

[英]Repository Pattern and MVC help

I'm new to C# and ASP.NET MVC and i'm trying to understand the repository pattern. 我是C#和ASP.NET MVC的新手,我正在尝试理解存储库模式。 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. 我目前正在使用LINQ to SQL访问我的SQL Server 2005数据库,出于测试目的,我创建了两个表。 I have an Employees table and an EmployeeContacts table. 我有一个Employees表和一个EmployeeContacts表。 The pk of both tables is UserName. 两个表的pk都是UserName。

Employees 雇员

  • UserName 用户名
  • LastName
  • FirstName 名字
  • Position 位置
  • Email 电子邮件
  • Status 状态

  • HireDate 聘用日期

EmployeeContacts EmployeeContacts

  • UserName 用户名
  • Contact1 Contact1
  • Contact1Phone Contact1Phone
  • Contact1Relationship 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. 可以添加,更新和删除EmployeeContacts表中的数据也可以添加,更新和删除。

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. 到目前为止,我有这个Employee存储库。 I also have one for EmployeeContacts . 我还有一个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 : 我有一个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 : 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 . 在我的视图中,我继承自@model MvcDirectoryLINQ.Models.EmployeeFormViewModel My Employee data saves correctly but the EmployeeContacts don't and I have no idea why. 我的员工数据保存正确,但EmployeeContacts没有,我不明白为什么。

Am I implementing the repository pattern correctly? 我是否正确实现了存储库模式?

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 ? EmployeeContacts可以独立于任何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. 如果是这样,请使用Employee存储库本身来管理它们。

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. 你没有在这里做过,因为你创建我可以看到你的EmployeeRepository类没有实现一个接口。 You really want to have something like EmployeeRepository : IEmployeeRepository 你真的想拥有像EmployeeRepository : IEmployeeRepository这样的东西EmployeeRepository : IEmployeeRepository

Then, in your Controller code, you can pass around an IEmployeeRepository instead of working concretely with your EmployeeRepository . 然后,在您的Controller代码中,您可以传递IEmployeeRepository而不是与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. 我注意到的另一件事是你存储库中启动了一个DataContext If you wanted to make changes to multiple different types of objects you would therefore have multiple DataContext s open, which I don't think is what you want, since your changes won't be transactional. 如果您想对多个不同类型的对象进行更改,那么您将打开多个DataContext ,我认为这不是您想要的,因为您的更改不会是事务性的。 You may want to look into the Unit of Work Pattern for a solution. 您可能需要查看Unit of Work模式以获得解决方案。

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. 祝好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM