MVC DDD:可以将存储库与控制器中的服务一起使用吗? [英] MVC DDD: Is it OK to use repositories together with services in the controller?

查看:20
本文介绍了MVC DDD:可以将存储库与控制器中的服务一起使用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大部分时间在服务代码中我都会有这样的东西:

public SomeService : ISomeService{ISomeRepository someRepository;公共做(int id){someRepository.Do(id);}}

所以有点多余

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

这样好吗?有没有这样的架构?

解决方案

您无法在两者之间建立业务逻辑.

我不同意这一点.

如果业务逻辑应该在它的位置 - 在域模型中,那么在控制器中调用 repo(或者更好 - 使用模型绑定器)来获取聚合根并调用它的方法对我来说似乎非常好.

当涉及过多的技术细节会导致控制器混乱时,应使用应用服务.

<小时><块引用>

我最近看到有几个人提到使用模型绑定器调用存储库.这个疯狂的想法从何而来?

我相信我们在这里谈论的是两种不同的事情.我怀疑您的模型绑定器"意味着同时将模型用作视图模型,并将更改后的值从 UI 直接绑定回它(这本身并不是一件坏事,在某些情况下我会走那条路).

我的模型绑定器"是一个实现IModelBinder',它在构造函数中获取存储库(它被注入,因此 - 如果我们需要一些基本组合的缓存,可以扩展)并在调用 action 之前使用它来检索聚合根并替换 intidGuid idstring slugwhatever 具有真实域对象的动作参数.将它与输入视图模型参数相结合可以让我们编写更少的代码.像这样:

public ActionResult ChangeCustomerAddress(客户 c, ChangeCustomerAddressInput inp){c.ChangeCustomerAddress(inp.NewAddress);return RedirectToAction("Details", new{inp.Id});}

在我的实际代码中,它有点复杂,因为它包括 ModelState 验证和一些可能从域模型内部抛出的异常处理(提取到控制器扩展方法中以供重用).但不多.到目前为止 - 最长的控制器动作大约有 10 行.

您可以看到工作实现(相当复杂并且(对我而言)不必要的复杂)这里.

<块引用>

你是在用 Linq To Sql 做 CRUD 应用程序还是在尝试使用真正的域逻辑?

如您所见(希望如此),这种方法实际上几乎迫使我们转向基于任务的 应用程序而不是基于 CRUD 的应用程序.

<块引用>

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

...并且拥有新的抽象层,邀请我们将基础架构与域逻辑混合在一起,并失去域模型的隔离性.

<块引用>

请赐教.

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

<小时>

这里是我当前的模型绑定器基类.这是我当前项目中的控制器操作之一.而且这里缺乏"业务逻辑.

most of the time in the service code I would have something like this:

public SomeService : ISomeService
{
    ISomeRepository someRepository;
    public Do(int id)
    {
        someRepository.Do(id);
    }
}

so it's kinda redundant

so I started to use the repositories directly in the controller

is this ok ? is there some architecture that is doing like this ?

解决方案

You lose the ability to have business logic in between.

I disagree with this one.

If business logic is where it should be - in domain model, then calling repo in controller (or better - use model binder for that) to get aggregate root and call method on it seems perfectly fine to me.

Application services should be used when there's too much technical details involved what would mess up controllers.


I've seen several people mention using model binders to call into a repo lately. Where is this crazy idea coming from?

I believe we are talking about 2 different things here. I suspect that Your 'model binder' means using model simultaneously as a view model too and binding changed values from UI directly right back to it (which is not a bad thing per se and in some cases I would go that road).

My 'model binder' is a class that implements 'IModelBinder', that takes repository in constructor (which is injected and therefore - can be extended if we need caching with some basic composition) and uses it before action is called to retrieve aggregate root and replace int id or Guid id or string slug or whatever action argument with real domain object. Combining that with input view model argument lets us to write less code. Something like this:

public ActionResult ChangeCustomerAddress
 (Customer c, ChangeCustomerAddressInput inp){
  c.ChangeCustomerAddress(inp.NewAddress);
  return RedirectToAction("Details", new{inp.Id});
}

In my actual code it's a bit more complex cause it includes ModelState validation and some exception handling that might be thrown from inside of domain model (extracted into Controller extension method for reuse). But not much more. So far - longest controller action is ~10 lines long.

You can see working implementation (quite sophisticated and (for me) unnecessary complex) here.

Are you just doing CRUD apps with Linq To Sql or trying something with real domain logic?

As You can (hopefully) see, this kind of approach actually almost forces us to move towards task based app instead of CRUD based one.

By doing all data access in your service layer and using IOC you can gain lots of benefits of AOP like invisible caching, transaction management, and easy composition of components that I can't imagine you get with model binders.

...and having new abstraction layer that invites us to mix infrastructure with domain logic and lose isolation of domain model.

Please enlighten me.

I'm not sure if I did. I don't think that I'm enlightened myself. :)


Here is my current model binder base class. Here's one of controller actions from my current project. And here's "lack" of business logic.

这篇关于MVC DDD:可以将存储库与控制器中的服务一起使用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆