Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc MVCDDD:在控制器中与服务一起使用存储库可以吗?_Asp.net Mvc_Model View Controller_Architecture_Domain Driven Design - Fatal编程技术网

Asp.net mvc MVCDDD:在控制器中与服务一起使用存储库可以吗?

Asp.net mvc MVCDDD:在控制器中与服务一起使用存储库可以吗?,asp.net-mvc,model-view-controller,architecture,domain-driven-design,Asp.net Mvc,Model View Controller,Architecture,Domain Driven Design,大多数情况下,在服务代码中,我会有如下内容: public SomeService : ISomeService { ISomeRepository someRepository; public Do(int id) { someRepository.Do(id); } } public ActionResult ChangeCustomerAddress (Customer c, ChangeCustomerAddressInput inp)

大多数情况下,在服务代码中,我会有如下内容:

public SomeService : ISomeService
{
    ISomeRepository someRepository;
    public Do(int id)
    {
        someRepository.Do(id);
    }
}
public ActionResult ChangeCustomerAddress
 (Customer c, ChangeCustomerAddressInput inp){
  c.ChangeCustomerAddress(inp.NewAddress);
  return RedirectToAction("Details", new{inp.Id});
}
所以它有点多余

所以我开始直接在控制器中使用存储库


这样行吗?是否存在这样的体系结构?

如果在控制器中使用存储库,则直接从数据层转到表示层。您将失去将业务逻辑置于两者之间的能力

现在,如果您说您只在需要业务逻辑时使用服务,并且在其他地方使用存储库,那么您的代码将成为一场噩梦。表示层现在正在调用业务层和数据层,并且您没有很好的关注点分离

我总是这样做:
存储库->服务->用户界面
。一旦您认为不需要业务层,需求就会发生变化,您将不得不重写所有内容

您将失去将业务逻辑置于两者之间的能力

我不同意这一点

若业务逻辑应该在域模型中,那个么在控制器中调用repo(或者更好地使用modelbinder)来获取聚合根并调用它的方法对我来说似乎非常好

当涉及太多技术细节时,应该使用应用程序服务,因为这些细节会使控制器陷入混乱



最近,我看到一些人提到使用模型绑定器进行回购。这个疯狂的想法是从哪里来的

我相信我们在这里谈论的是两件不同的事情。我怀疑您的“模型绑定器”意味着同时使用模型作为视图模型,并将更改的值从UI直接绑定回它(这本身并不是一件坏事,在某些情况下,我会这样做)

我的“模型绑定器”是一个实现“”的类,它在构造函数中接受存储库(它被注入,因此,如果我们需要一些基本组合的缓存,它可以被扩展)并在调用action之前使用它来检索聚合根并用实域对象替换
int-id
Guid-id
string-slug
任何
操作参数。结合输入视图模型参数,我们可以编写更少的代码。大概是这样的:

public SomeService : ISomeService
{
    ISomeRepository someRepository;
    public Do(int id)
    {
        someRepository.Do(id);
    }
}
public ActionResult ChangeCustomerAddress
 (Customer c, ChangeCustomerAddressInput inp){
  c.ChangeCustomerAddress(inp.NewAddress);
  return RedirectToAction("Details", new{inp.Id});
}
在我的实际代码中,它有点复杂,因为它包括ModelState验证和一些可能从域模型内部抛出的异常处理(提取到控制器扩展方法中以供重用)。但没有更多。到目前为止,最长的控制器动作约10行

您可以看到工作实现(非常复杂,而且(对我来说)不必要的复杂)

你只是在用LINQtoSQL做CRUD应用,还是在用真正的域逻辑做一些尝试

正如您(希望)看到的,这种方法实际上几乎迫使我们转向应用程序,而不是基于CRUD的应用程序

通过在服务层中进行所有数据访问并使用IOC,您可以获得AOP的许多好处,如不可见缓存、事务管理和组件的轻松组合,这些是我无法想象的,您可以通过模型绑定获得这些好处

…并且有了新的抽象层,邀请我们将基础架构与域逻辑混合,并失去域模型的隔离

请开导我

我不确定我是否做到了。我不认为我自己开悟了。:)



是我当前的模型绑定器基类。我当前项目中的一个控制器操作。“缺少”业务逻辑。

即使使用“富域模型”,您仍然需要一个域服务来处理涉及多个实体的业务逻辑。我还从来没有见过没有一些业务逻辑的CRUD,只是在简单的示例代码中。我总是希望遵循Martin的路线来保持代码的简洁。

我自己的DDD/MVC的粗略实践:

  • 控制器是特定于应用程序的,因此它们应该只包含特定于应用程序的方法和调用服务方法
  • 所有公共服务方法通常都是原子事务或查询
  • 仅服务实例化和调用存储库
  • my Domain定义了一个IContextFactory和一个IContext(由于IContext成员是IDBSet,所以存在大量泄漏的抽象)
  • 每个应用程序都有一种类型,主要是实例化一个上下文工厂以传递给服务(您可以使用DI容器,但不是什么大问题)
这迫使我将业务代码和数据访问排除在控制器之外。我发现这是一个很好的纪律,因为当我不遵守上面的规定时,我是多么的放松

事情是这样的

“业务逻辑”应该驻留在实体和值对象中

存储库只处理AggregateRoot。因此,在控制器中直接使用存储库有点像是将该操作视为“服务”。此外,由于AggregateRoot只能通过其ID引用其他AR,因此您可能需要调用一个或多个repo。它真的很快变得很糟糕

如果您打算提供服务,请确保公开POCO,而不是实际的AggregateRoot及其成员

除了创建、检索、更新和删除内容之外,您的回购协议不应该执行任何操作。您可能有一些基于特定条件的定制检索,但仅此而已。因此,在您的回购协议中有一个方法与您的服务中的方法相匹配。。。代码就在那里

您的服务是面向API的。想想这个。。。如果您要将该服务打包到.dll中供我使用,您将如何以一种便于我了解您的服务可以做什么的方式创建您的方法?更新(对象)没有多大意义

我甚至还没谈过CQR。。。事情变得更加有趣

您的Web Api只是您服务的客户端。您的服务可以被其他服务使用,对吗?那么,瘦