【问题标题】:MVC repository architecture and accessing different tablesMVC 存储库架构和访问不同的表
【发布时间】:2012-08-03 23:16:51
【问题描述】:

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

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

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

两个存储库都设置为处理依赖注入,但也有 0 个参数构造函数,默认使用适当的 EF 数据访问。

销售人员控制器使用 _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 对象(在 salesRepository 中)应该通过 salesPerson 存储库访问,还是直接从 dataContext 对象访问?

感谢您的想法和经验

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 在这种情况下不应该使用服务吗?那么服务包含两个不同的存储库?
    • @Captain0 是的,这是可取的,请参阅此处:stackoverflow.com/a/41298045/1019850。此答案muddies the water 中的解决方案带有混合存储库,负责两个不同的域实体和一个服务是更好的解决方案。
    【解决方案2】:

    首先,应遵循 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 容器中的每个请求中,而不是直接在控制器中创建,大多数 IoC 容器都支持这一点。不知道您使用哪个 IoC 容器,但我最喜欢的是:Autofac 和 Windsor。

    对于 c 项,您正在使业务逻辑泄漏到 Repository 层,相反,业务逻辑应该在控制器或单独的层中。存储库只处理您的数据库的 CRUD 操作。

    【讨论】:

      【解决方案3】:

      最佳实践始终取决于上下文,但在 EF 之上经常使用 RepositoryUnit Of Work 模式的组合.

      用法:

      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();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-06-28
        • 1970-01-01
        • 2016-04-30
        • 2019-02-28
        • 2020-03-16
        • 2023-03-27
        • 1970-01-01
        • 2013-10-25
        • 1970-01-01
        相关资源
        最近更新 更多