c# - 实体中的业务逻辑并注入(inject) DbContext

标签 c# asp.net-mvc linq entity-framework unit-testing

我知道围绕这个主题有很多话题,但我没有找到让我满意并真正解释如何在 Entity Framework 内开发业务逻辑的帖子。因此,在这篇文章中,我想总结一下我通过阅读其他各种文章所获得的知识,然后请您帮助我清理思绪。

实体:这些是我的类,映射到数据库中的表,如用户、交易、订单等。这些是 POCO 对象(我使用代码优先方法使用它们)。

域模型:这是业务逻辑应该存在的地方。我花了很长时间才发现域模型与 EF 的实体不同。

服务层:我发现一开始就不需要服务层。它可用于将一些东西带入其中,但通常业务逻辑应该在模型中。所以最好把它说出来

Repository-Layer: 好的,我们可以使用 CRUD 方法(如 IEnumerable GetUsers())编写一个存储库,这使得测试更容易,但是另一方面,我们将失去整个 LINQ 功能,并且需要编写更多内容。为了进行测试,我还可以模拟 EF Framework,因此对我来说,存储库层已经结束。

工作单元:DbContext 本身就是一个工作单元。所以我不必在这里编写任何特殊代码,只需将 DbContext 传递给我的所有方法并在完成时调用 SaveChanges。

Lazy-Loading:有时我确实使用它,有时我确实使用 Eage Loading。但与此同时我发现,当你想做工作单元的事情并保持你的代码干净时,延迟加载是必须的。当您在一个方法中并从另一个方法中获取一些代码传递给该方法时,该方法又从另一个方法中获取代码……您只想访问属性。您不关心数据是否存在。它必须自动加载。所以我想知道如何在没有任何延迟加载的情况下做到这一点。

DbContextScopes:正如在其他帖子中讨论的那样,我们不应该在应用程序实例上使用 DbContext,我们也不应该在每个请求中使用它。相反,我们应该为当前任务创建一个 DbContext 并将其传递给所有需要的方法。使用 [DbContextScopeFactory][1] 可以使这更容易。

依赖注入(inject):我总是应该使用 DI 在构造函数中注入(inject)所需的东西。这是有道理的,因为当我们进行单元测试时,我们可以放入模拟资源。我还读到属性注入(inject)不太好,不应该使用。

交易:不应再使用,因为它们有很多问题。而是坚持使用工作单元(它在内部使用事务?!)并以这种方式为您的架构建模。

所以现在我想知道如何真正使用这些东西。

问题一:模型=实体?

我们应该创建某种单独的域模型还是可以将其包含在实体模型中?我认为额外的域模型似乎可以处理很多代码。为什么不将逻辑写入实体?有什么问题?

问题二:如何获取DbContext?

当我添加一个实体时,我不想添加基础设施之类的东西

order.Lines.Add(new OrderLine(product, qty, text));

而不是

order.Lines.Add(new OrderLine(dbcontext, product, qty, text));

也许属性依赖注入(inject)是一种解决方案,但如前所述,这也不是一个好的模式......

最佳答案

问题一

您的域模型应该代表您的数据库,并且干净、轻便,以便轻松地将数据从数据库传输到应用程序的任何部分。如果您向模型添加逻辑,它们很快就会变得臃肿和沉重,因此每次您新建每个域模型的实例时,无论是否使用它,您的逻辑都会随之而来!

如果您开始将所有逻辑放入您的域模型中,您很快就会意识到您想要访问其他域模型的属性,然后您必须开始将它们相互传递,很快就会变得困惑。它唯一有用的是您只需编写一次代码,但这就是将您的逻辑分离到服务层中的好处变得显而易见的地方。

拥有服务层的美妙之处在于,每个服务都可以包含在您的 DTO 和(轻量级)领域模型上执行特定功能或功能组的逻辑,它们只需要编写一次并且可以使用相同的代码在整个应用程序中多次。您可以将服务接口(interface)出来,并在需要时将每个服务作为依赖项添加到您的 Controller ,这样您只将它们暴露给每个 Controller 实际需要的服务中逻辑的特定部分,而不是对于您之前可能已经写入领域模型的每条逻辑,都需要更长的时间。

拥有一个服务层也应该显着减少 Controller 中的代码量,因为您的业务逻辑将在您的服务中执行,而 Controller 操作将仅用于将值传递给您的服务以进行处理和映射他们返回到您的 View 模型。

问题二

根据您正在做的事情(如果您没有在请求中使用多线程),通常每个 HTTP 请求您应该有一个新的 DbContext - 这可以使用大多数 DI 容器进行配置。我会 get yourself an Interface for the DbContext并在您的 MVC 应用层中对其进行配置,并将其向上注入(inject)到您的服务层中。

...

关于c# - 实体中的业务逻辑并注入(inject) DbContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31703585/

相关文章:

c# - 如何在多个 View 之间共享一个绑定(bind)值?

c# - MAF 安全 : How to prevent a "Man-in-the-Middle" Attack

asp.net-mvc - VB.Net 中的 ASP.Net session

c# - 字符串字段长度限制和换行

c# - C#/LINQ 中的嵌套 .SelectMany 语句

c# - 从进程访问 FileName 仅在 Debug 语句之后有效?

c# - 使用多个 JWT 承载身份验证

asp.net-mvc - asp.net mvc 和自定义成员资格和角色提供程序

c# - 复杂的 LINQ 查询

C# 如果值不为 null,为什么 Linq 会因 Null 而崩溃?