【问题标题】:ASP.Net MVC: working with multiple repositories & injection by Unity DIASP.Net MVC:使用多个存储库和 Unity DI 注入
【发布时间】:2018-02-15 22:07:00
【问题描述】:

我正在使用 asp.net mvc 5 项目。假设我在显示客户详细信息和客户最喜欢的产品的位置显示客户数据。

所以我从客户存储库、国家存储库和最喜欢的存储库中获取数据。

很多时候人们都在Unity DI上写过关于注入库的文章。当我使用单个存储库时,这个概念是有意义的,但是当我必须从多个存储库中获取数据时,我如何通过 unity di 在 mvc 控制器 ctor 中注入多个存储库?

查看统一 DI 注入存储库的小代码。

public class FooController : Controller  
{  
     readonly IFooRepository _repository;  

     // Inject here  
     public ProductController(IFooRepository repository)  
     {  
           _repository = repository;   
     }  

     // Use it here  
     public ActionResult Bar()  
     {  
          var bar = _repository.DoSomething();  
     }  
}  

以上代码来自https://forums.asp.net/t/2105895.aspx?Repository+inject+into+controller+by+Unity+DI

现在告诉我如何重构我的代码或我应该遵循什么方法,因此我可以使用多个存储库,也可以通过 Unity DI 注入。

请给我最好的指导。谢谢

【问题讨论】:

    标签: asp.net-mvc dependency-injection unity-container


    【解决方案1】:

    只需将所需的任何依赖项添加到控制器的构造函数中即可。

    public class FooController : Controller  
    {  
        readonly IFooRepository _repository;  
        readonly IOtherRepository _otherRepository;  
    
        public ProductController(IFooRepository repository, IOtherRepository otherRepository)  
        {  
            _repository = repository;   
            _otherRepository = otherRepository;
        }  
    

    【讨论】:

      【解决方案2】:

      请注意,虽然 L-Fourresponse 通常是一个不错的方法,但稍后当您对加载的实体进行一些修改并想要保存它们时,您可能会遇到困难,因为您可能最终在存储库中拥有单独的 DBContext 实例。但这取决于您的存储库和 DI 实现和配置...

      例子:

      // Assume you want to create a new User with associated Account
      
      var user = _usersRepository.AddUser(new User(....));
      var account = _accountRepository.AddAccount(new Account{ ... User = user });
      
      // Now you want to save them both in one transaction... how?
      _usersRepository.Commit();
      _accountRepository.Commit(); // What if this fails? you have an orphaned user?
      

      为了解决这个问题,我建议实施所谓的 Unit Of Work 模式。在Stack Overflowelsewhere 上也有一些good examples

      以后可能会让你头疼。

      您的更新代码将是:

      public class FooController : Controller  
      {  
           readonly IUsersAndAccountUnitOfWork _uow;  
      
           // Inject here  
           public ProductController(IUsersAndAccountUnitOfWork uow)  
           {  
                 _uow = uow;
           }  
      
           // Use it here  
           public ActionResult Bar()  
           {  
                 var user = _uow.Users.AddUser(new User(....));
                 var account = _uow.Accounts.AddAccount(new Account{ ... User = user });
      
                 _uow.Commit();
           }  
      } 
      

      【讨论】:

      • 您可以简单地注册 db 上下文,只存在一个实例,并且它只存在于特定(Web)请求的范围内。
      • @L-四 是的!但最好有一个Commit 方法。如果它在存储库级别,我希望它实际上仅适用于该存储库,例如userRepository.Commit() 应该只将我的更改提交给用户,我不希望它也提交 myOtherRepository 中的更改。
      • @thmshd 您能否发布一个完整的小示例代码来展示您的代码流程?您是否使用任何 DI 在 IRepository 和 Repository 之间进行映射以自动传递给控制器​​?
      • 我不会在存储库中公开提交。上下文的创建和销毁独立于存储库,并作为依赖项传递给存储库。
      • @L-Four 我也不会在存储库中公开提交,我不明白您如何尝试一次提交跨多个存储库完成的多项更改。你的Commit 方法在哪里,谁负责在 DbContext 上执行Commit?当然,您不希望每个 AddXYZ(...) 方法都提交,您需要控制它,因为您可能需要新的实体 ID 进行进一步处理。这就是 Unit Of Work 模式发挥作用的地方。
      猜你喜欢
      • 1970-01-01
      • 2011-02-14
      • 2019-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多