【发布时间】:2015-10-20 14:51:31
【问题描述】:
我知道围绕这个主题有很多线程,但我没有找到任何让我满意并真正解释如何在实体框架内开发业务逻辑的帖子。所以在这篇文章中,我想总结一下我通过阅读其他各种帖子所得到的信息,然后请你帮我清理一下思路。
实体:这些是我的类,它们映射到数据库中的表,如用户、事务、订单等。这些是 POCO 对象(我将它们与 Code-First 方法一起使用)。
域模型:这是业务逻辑应该在的地方。我花了很长时间才发现域模型与 EF 的实体不同。
服务层:我发现一开始就不需要服务层。它可以用来将一些东西带入其中,但通常业务逻辑应该在模型中。所以最好把它说出来
Repository-Layer:好的,我们可以编写一个带有 CRUD-Methods 的存储库,例如 IEnumerable GetUsers(),这使测试更容易,但另一方面,我们将失去整个 LINQ 功能,而且要编写更多内容。为了测试,我还可以模拟 EF 框架,所以对我来说,存储库层已经出来了。
工作单元: DbContext 本身就是一个工作单元。所以我不必在这里编写任何特殊的代码,我只需将 DbContext 传递给我的所有方法并在完成后调用 SaveChanges。
延迟加载:有时我确实使用它,有时我确实使用 Eage Loading。但与此同时,我发现,当您想要执行工作单元并保持代码干净时,延迟加载是必须的。当您在一个方法中并从另一个方法中获取一些传递给该方法的代码时,又从另一个方法中获取了它……您只想访问属性。你不在乎数据是否在那里。它必须自动加载。所以我想知道如何在没有任何延迟加载的情况下做到这一点。
DbContextScopes: 正如在其他帖子中讨论的那样,我们不应该在应用程序实例上使用 DbContext,我们也不应该在每个请求中都使用它。相反,我们应该为当前任务创建一个 DbContext 并将其传递给所有需要的方法。使用 [DbContextScopeFactory][1] 可以使这变得更容易。
依赖注入: 我总是应该使用 DI 在构造函数中注入需要的东西。这是有道理的,因为当我们进行单元测试时,我们可以放入模拟资源。我还读到属性注入不太好,不应该使用。
事务:不应再使用,因为它们有很多问题。而是坚持使用 Unit-Of-Work(它在内部使用事务?!)并以这种方式为您的架构建模。
所以现在我想知道如何真正使用这些东西。
问题 1:模型 = 实体?
我们应该创建某种单独的域模型还是可以将其包含在实体模型中?我认为一个额外的域模型似乎是很多代码的方式。为什么不将逻辑写入实体?有什么问题?
问题2:如何获取DbContext?
当我添加一个实体时,我不想添加基础设施的东西,比如
order.Lines.Add(new OrderLine(product, qty, text));
而不是
order.Lines.Add(new OrderLine(dbcontext, product, qty, text));
也许属性依赖注入是一种解决方案,但正如所说的那样,这也不是一个好的模式......
【问题讨论】:
标签: c# asp.net-mvc linq entity-framework unit-testing