使用每个控制器创建新存储库

时间:2014-04-17 12:02:52

标签: asp.net-mvc asp.net-mvc-3 linq-to-sql repository-pattern

我一直在阅读Dependency IncectionUnitOfWorkIRepository模式,我打算随着时间的推移实施这些模式。但是一下子就可以接受很多东西。现在我只想确定一些基本的东西,并且我不会错过任何可能影响我的应用程序的重要事项。

应用程序相当小,任何给定点的同时用户数不会超过10个。

AdressRegDataContext是生成的dbml(使用Visual Studio Add - > Linq to SQL类)。

我的问题 关注下面添加第二个控制器:

  • 在这样的每个控制器中创建新存储库是否有任何问题?

对我而言,如果两个用户同时使用该应用程序,则会感觉有两个不同的上下文。或者datacontext为我处理?单身知识库在理论上是有道理的,但我已经读过那个 nono ,所以我不会这样做。

我有一个我使用的存储库:

存储库

namespace AdressReg.Models
{
    public class AdressRegRepository
    {
        private AdressRegDataContext db = new AdressRegDataContext();

        // Return person by id
        public Person GetPerson(int id)
        {
            return db.Persons.SingleOrDefault(p => p.id == id);
        }

        // Return student by id
        public Student GetStudent(int id)
        {
            return db.Students.SingleOrDefault(s => s.id == id);
        }
    }
}

到目前为止,我只使用了一个控制器:

HomeController

namespace AdressReg.Controllers
{
    public class HomeController : Controller
    {
        AdressRegRepository repository = new AdressRegRepository();

        // GET: /Home/Person
        public ActionResult Person(int id)
        {
            PersonView view = new PersonView();
            view.person = repository.GetPerson(id);

            return View(view);
        }
    }
}

但我打算增加另一个:

EducationController

namespace AdressReg.Controllers
{
    public class EducationController: Controller
    {
        AdressRegRepository repository = new AdressRegRepository();

        // GET: /Education/Student
        public ActionResult Student(int id)
        {
            StudentView view = new StudentView();
            view.student = repository.GetStudent(id);

            return View(view);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

是的。首先,这不是一个“真正的”存储库,在EF之上是一个无用的抽象,你可以抛弃它。存储库应返回业务或应用程序对象而不是EF实体。出于查询目的,它应至少返回视图模型的一些位(如果不是全部)。因此,它应该返回PersonView或StudentView。这些是指导性而非绝对真理或规则,但您确实需要了解设计模式的目的,在本例中是存储库。而且你的代码显示你还没有理解它。

在你的应用程序中,repo没有做任何有用的事情,所以直接使用ORM,它更简单。

您的控制器与特定的具体存储库紧密耦合。关键是你应该定义一个抽象并将其作为构造函数中的依赖项传递。像

这样的东西
 // a better name is needed, this would be a query repository
public interface IAddressesRegRepository
{
    StudentView Get(int it);
}

public class MyController:Controller
{
    IAddressesRegRepository _repo;   
    public MyController(IAddressesRegRepository repo) 
    {
        _repo=repo;
     }

     public ActionResult Student(int id)
    {
        StudentView view = _repo.GetStudent(id);

        return View(view);
    }

 }

如您所见,控制器现在依赖于抽象,DI Container将在创建控制器时注入具体实现。它将允许您模拟存储库并具有多个实现。同样的方法适用于您想在控制器中使用的所有内容。

关于存储库,我更喜欢拥有不同的业务/查询存储库(虽然现在我正在使用查询处理程序),即我不会在域存储库中放置查询行为,除非业务层本身需要它。

对于严格查询,使用EF非常简单,或者如果您的查询很丑或想要稍后更改实现,请使用构建视图模型的查询对象/ repository / service / handler(无论如何调用它)来自坚持。关键是要在DAL中保留持久性详细信息(ORM,EF Entites),您的UI不应该知道它们。在您的示例中,UI了解EF entites。

再一次,我所说的是指导方针,当你获得更多经验时,你会知道何时弯曲(打破)它们而没有令人讨厌的副作用。