MVC存储库体系结构和访问不同的表

时间:2012-08-06 23:54:11

标签: c# .net asp.net-mvc architecture

感谢您帮助我理解其中的一些内容:

假设我在MVC应用程序中有2个控制器 - 1控制与销售人员相关的viewModels 1控制与销售相关的viewModels

每个都有自己的存储库,使用Entity框架(代码优先)访问数据

这两个存储库都设置为处理依赖注入,但也有0个参数构造函数,默认值使用相应的EF dataAccess。

salespeople控制器使用_salesPeopleRepository.getAllSalesPeople()函数返回一个销售人员列表来填充索引视图。

销售控制器需要访问相同的列表来填充下拉列表。

有几种方法可以将信息提供给销售控制人员,我想知道哪些选项被认为是最佳做法:

a)在控制器中

db = new DataContext();
_saleRepos = new SalesRepository(db);
_salesPeople = new SalesPeopleRepository(db);
 .....
modelA.SalePeopleSelectList = SelectList(_salesPeople.getAllSalesPeople(),"id","name")

b)在SalesRepository中 - 使用EF本身:

public IEnumerable<salesPerson> getAllSalesPeople()
{ 
    return _db.SalesPeople.ToList();
}

c)或在调用函数

之前实例化并注入相同的数据访问对象
public IEnumerable<salesPerson> getAllSalesPeople()
{ 
    return (new SalesPersonRepository(_db)).getAllSalesPeople();
}

修改

如果答案是a),应如何从1个存储库调用自定义商务逻辑 - 例如,sales有一个storeId,并且存储库检查为销售输入的storeId是否与salesPerson的storeId匹配。是否应该通过salesPerson存储库或直接从dataContext对象访问用于商业逻辑目的的salesPerson对象(在salesRepository中)?

感谢您的想法和经验

3 个答案:

答案 0 :(得分:5)

SalesRepository表中检索SalesPerson数据是没有意义的。数据访问逻辑应该集中在SalesPeopleRepository中。在我看来,在存储库中复制方法只会使水变得混乱。

那么为什么不在销售控制器中同时使用SalesRepositorySalesPeopleRepository?我只是实例化SalesPeopleRepository的一个实例,并使用那里已经定义的方法。

此外,如果您的控制器使用依赖注入,您可以将存储库传递给构造函数:

public SalesController (ISalesRepository salesRepository, ISalesPeopleRepository salesPeopleRepository)
{
   this._salesRepository = salesRepository;
   this._salesPeopleRepository = salesPeopleRepository;
}

答案 1 :(得分:2)

最佳实践总是取决于具体情况,但在EF之上经常使用存储库工作单元模式的组合

<强>用法:

using (var uow as new DataContext()) {
    var salesPeople = new SalesPeopleRepository(uow);

    // ...

    uow.Commit(); // If changes must be committed back to the database
}

<强>实施

public interface IUnitOfWork {
    public void Commit();
}

public class DataContext : IUnitOfWork {
    public void Commit() {
        this.SaveChanges();
    }
}

public class SalesPeopleRepository {

    private DataContext _db

    public SalesPeopleRepository(IUnitOfWork uow) {
        _db = uow as DataContext;
    }

    public IEnumerable<SalesPerson> GetAllSalesPeople() { 
        return _db.SalesPeople.ToList();
    }
}

答案 2 :(得分:1)

首先,应该遵循C#命名约定:getAllSalesPeople()应该是GetAllSalesPeople。其次,在这种情况下,IoC容器和依赖注入将是最佳实践。

应该避免使用 a 项,因为DataContext和Repositories直接在控制器中创建,它违反了依赖注入并使您的代码与Repositories和DataContext紧密耦合,无法模拟单元测试。相反,应将存储库注入控制器,并将DataContext注入存储库。

public Repository(DataContext dataContext)
{
    _dataContext = dataContext;
}

public SalesController(ISalesRepository salesRepository, 
                          ISalesPeopleRepository salesPeopleRepository) 
{ 
   _salesRepository = salesRepository; 
   _salesPeopleRepository = salesPeopleRepository; 
} 

DataContext的生命周期管理应保存在IoC Container中的每个请求中,而不是直接在控制器中创建,大多数IoC Container都支持此操作。不知道你使用的是哪个IoC容器,但我最喜欢的是:Autofac和Windsor。

对于项目 c ,您将业务逻辑泄漏到存储库层,而业务逻辑应位于控制器或单独的层中。存储库只处理您的数据库的CRUD操作。