数据库抽象层设计 - 以正确的方式使用IRepository?

时间:2010-02-27 12:43:42

标签: .net asp.net-mvc database-abstraction

我正在设计我的ASP.NET MVC应用程序,我遇到了一些有趣的想法。

我见过的很多样本都描述并使用了Repository模式(IRepository),所以这就是我在学习MVC时的方式。

现在我知道它正在做什么,我开始看看我目前的设计,并想知道这是否是最好的方式。

目前我有一个基本IUserRepository,它定义了FindById()SaveChanges()等方法。

目前,每当我想在数据库中加载/查询用户表时,我都会按照以下方式执行操作:

    private IUserRepository Repository;

    public UserController()
        : this(new UserRepository())
    { }

    [RequiresAuthentication]
    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Edit(string ReturnUrl, string FirstRun)
    {
        var user = Repository.FindById(User.Identity.Name);

        var viewModel = Mapper.Map<User, UserEditViewModel>(user);
        viewModel.FirstRun = FirstRun == "1" ? true : false;

        return View("Edit", viewModel);
    }

    [AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken(Salt = "SaltAndPepper")]
    public ActionResult Edit(UserEditViewModel viewModel, string ReturnUrl)
    {
        //Map the ViewModel to the Model
        var user = Repository.FindById(User.Identity.Name);

        //Map changes to the user
        Mapper.Map<UserEditViewModel, User>(viewModel, user);

        //Save the DB changes
        Repository.SaveChanges();

        if (!string.IsNullOrEmpty(ReturnUrl))
            return Redirect(ReturnUrl);
        else
            return RedirectToAction("Index", "User");
    }

现在我还不完全了解MVC在用户创建链接时如何工作(不确定每个用户是否有1个控制器或每个应用程序有1个控制器),所以我不是肯定的最好的行动方案。

我发现了一个关于使用通用存储库接口IRepository<T> here的一个很好的问题,并且在许多博客上似乎也有静态RepositoryFactory的想法。基本上只保留一个存储库实例,它是通过这个工厂获得的

所以我的问题围绕着人们如何在应用程序中执行此操作,以及什么是良好的实践。

人们是否根据每个表格(IUserRepository)设置了单独的存储库? 他们使用通用IRepository<T>吗? 他们是否使用静态存储库工厂? 还是别的什么呢?

编辑: 我刚才意识到我也应该问:

每个控制器上有一个私有IRepository是一个好方法吗?或者我应该每次想要使用它时实例化一个新的IRepository

BOUNTY编辑: 我开始获得更多的观点(不是蒂姆没有帮助)。

我更想知道人们在他们的MVC应用程序中做了什么,或者他们认为什么是个好主意。

5 个答案:

答案 0 :(得分:24)

答案 1 :(得分:3)

人们是否有基于每个表(IUserRepository)的个人存储库? 我倾向于为每个聚合而不是每个表都有一个存储库。

他们是否使用通用IRepository? 如果可能的话,是的

他们是否使用静态存储库工厂? 我更喜欢通过IOC容器注入Repository实例

答案 2 :(得分:1)

以下是我如何使用它。我正在使用IRepository进行我所有存储库共有的所有操作。

public interface IRepository<T> where T : PersistentObject
{
    T GetById(object id);
    T[] GetAll();
    void Save(T entity);
}

我还为每个aggregate使用了一个专用的ITRepository,用于与此存储库不同的操作。例如,对于用户,我将使用IUserRepository添加与UserRepository不同的方法:

public interface IUserRepository : IRepository<User>
{
    User GetByUserName(string username);
}

实现将如下所示:

public class UserRepository : RepositoryBase<User>, IUserRepository
{
    public User GetByUserName(string username)
    {
        ISession session = GetSession();
        IQuery query = session.CreateQuery("from User u where u.Username = :username");
        query.SetString("username", username);

        var matchingUser = query.UniqueResult<User>();

        return matchingUser;
    }
}


public class RepositoryBase<T> : IRepository<T> where T : PersistentObject
{
    public virtual T GetById(object id)
    {
        ISession session = GetSession();
        return session.Get<T>(id);
    }

    public virtual T[] GetAll()
    {
        ISession session = GetSession();
        ICriteria criteria = session.CreateCriteria(typeof (T));
        return criteria.List<T>().ToArray();
    }

    protected ISession GetSession()
    {
        return new SessionBuilder().GetSession();
    }

    public virtual void Save(T entity)
    {
        GetSession().SaveOrUpdate(entity);
    }
}

在UserController中将显示为:

public class UserController : ConventionController
{
    private readonly IUserRepository _repository;
    private readonly ISecurityContext _securityContext;
    private readonly IUserSession _userSession;

    public UserController(IUserRepository repository, ISecurityContext securityContext, IUserSession userSession)
    {
        _repository = repository;
        _securityContext = securityContext;
        _userSession = userSession;
    }
}

使用自定义控制器工厂使用依赖注入模式实例化存储库。我正在使用StructureMap作为我的依赖注入层。

数据库层是NHibernate。 ISession是此会话中数据库的网关。

我建议您查看CodeCampServer结构,您可以从中学到很多东西。

您可以从中学到的另一个项目是Who Can Help Me。我还没有深入挖掘它。

答案 3 :(得分:0)

人们是否根据每个表(IUserRepository)拥有单独的存储库?

是的,这是更好的选择,有两个原因:

  • 我的DAL基于 Linq-to-Sql (但我的DTO是基于LTS实体的接口)
  • 执行的操作是原子(添加是原子操作,另一个是保存等)。

他们是否使用通用IRepository?

是的,完全,受DDD实体/价值计划启发我创建了IRepositoryEntity / IRepositoryValue和其他东西的通用IRepository。

他们是否使用静态存储库工厂?

是和否:我使用通过静态类调用的 IOC容器。 嗯......我们可以说它是一种工厂。

注意:我自己设计了这个架构,我的一位同事发现它非常棒,我们目前正在这个模型上创建我们的整个公司框架(是的,它是一家年轻的公司)。这绝对是值得尝试的事情,即使我觉得那些框架将由主要演员发布。

答案 4 :(得分:0)

您可以找到一个出色的 Generic Repopsitory 库,以便在Codeplex上使用它作为WebForms asp:ObjectDataSource:MultiTierLinqToSql

我的每个控制器都有他们需要支持的操作的私有存储库。