问题标签 [persistence-ignorance]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
395 浏览

domain-driven-design - 使用 DDD、SOA 和 PI 提供帮助

在不涉及所有血腥细节的情况下,我正在尝试设计一个将由多个客户端应用程序使用的基于服务的解决方案。该解决方案允许管理员创建和修改普通用户用来执行数据输入的文档模板。我的目的是使该应用程序成为最佳实践、技术等的学习工具。

而且,与此同时,我必须适应精神分裂的环境,因为“当权者”永远无法坚持他们关于技术和工具的决定。例如,我今天使用的是 Linq-to-SQL,因为他们还没有准备好转到 EF4,但也有关于切换到 NHibernate 的讨论。因此,我必须使代码尽可能持久无知,以尽量减少更改 OR/M 工具所需的工作。

在这一点上,我也仅限于使用部分类方法来扩展 Linq-to-SQL 类,以便它们实现在我的业务层中定义的接口。我不能使用 POCO,因为管理层坚持要我们利用所有内置工具等,所以我必须支持 Linq-to-SQL 设计器。

也就是说,我的服务接口有一个 StartSession 方法,该方法在其签名中接受模板标识符。操作流程如下:

  1. 如果当前用户和指定模板的数据库中已经存在会话,则更新记录以显示当前活动。如果没有,则创建一个新的会话对象。
     
  2. 会话与模板的一个实例相关联,称之为“表单”。因此,如果会话是新的,我需要检索模板信息来创建新的“表单”,将其与会话相关联,然后将会话保存到数据库中。另一方面,如果会话已经存在,那么我还需要使用用户输入并存储在会话中的数据加载“表单”。
     
  3. 最后,会话(带有表单定义和数据)返回给调用者。
     

我的第一个目标是在我的应用程序的逻辑层之间创建清晰的分离。二是保持执着无明(如上所述)。第三,我必须能够测试所有内容,因此必须将所有依赖项外部化以便于模拟。我使用 Unity 作为 IoC 工具来帮助解决这个问题。

为此,我根据需要定义了我的服务类和数据协定以支持服务接口。服务类将具有从实际执行工作的业务层注入的依赖项。这对我来说是一团糟。

我一直在尝试使用工作单元和存储库路线来帮助解决持久性无知。我有一个 ITemplateRepository 和一个 ISessionRepository ,我可以从我的 IUnitOfWork 实现中访问它们。服务类获得了我的 SessionManager 类(在我的 BLL 中)注入的实例。SessionManager 通过构造函数注入接收 IUnitOfWork 实现,并将所有持久性委托给 UoW,但我发现自己在玩各种逻辑的 shell 游戏。

上面描述的所有逻辑都应该在 SessionManager 类中还是在 UoW 实现中?我希望存储库实现中的逻辑尽可能少,因为更改数据访问平台可能会导致对应用程序逻辑进行不必要的更改。由于我的存储库正在针对一个接口工作,我如何最好地创建新会话(请记住,有效的会话具有对模板的引用,呃,正在使用的表单)?即使我必须支持设计人员并在存储库实现中使用像 AutoMapper 这样的工具来处理对象的翻译,仍然使用 POCO 会更好吗?

啊!

我知道我只是陷入了分析瘫痪,所以我可能只需要一点推动。理想的情况是,如果有人可以提供一个示例,在给定我定义的业务规则和架构约束的情况下,您将如何解决问题。

0 投票
2 回答
917 浏览

wcf - 实体框架 - 架构升级、多 DBMS 和代码优先

我正在考虑在即将推出的项目中使用 Microsoft 的实体框架,该项目是现有产品的点发布。我们当前的产品支持两个 DBMS(Oracle 和 SQL Server),每个的架构都保存在单独的 .sql 脚本文件中。

实体框架 (4.1) 看起来很吸引人,因为它允许通过代码生成、反射等自动实现各种场景。但是,据我所知,其中一些好处似乎是相互排斥的。

例如,为了支持多个 DMBS,我推断我需要使用模型或代码优先设计,在这种情况下,EF 将根据模型为每个 DMBS 生成模式(我几乎没有看到关于此的帖子或文档,所以我可能是错的)。这意味着我们现有的模式需要被放弃(模型优先)或映射(代码优先)。此外,更新架构需要手动脚本,因为 EF 似乎不支持架构升级(不清除数据)。

  1. 模型优先和代码优先是在 EF 中支持多个 DBMS 的唯一可行方法吗?我意识到从技术上讲,不可能保证两个任意模式是相同的,所以我认为这是真的。
  2. 代码优先和映射到多个 DBMS 系统是否存在任何潜在缺陷?例如,Oracle 没有自增列;你必须使用序列。这在 DbContext 中是如何映射的?我需要为每个 DBMS 创建单独的映射吗?
  3. EF 是否支持将现有 DBMS 模式升级到代表 EF 模型的任何机制(模式重新创建 =/= 升级),或者我是否仅限于手动执行此操作?
  4. 我确实想出了一种可能的方法来首先使用数据库并支持多个 DBMS,但这是维护的噩梦。这个想法是为两个生成的数据模型添加另一层抽象,并为每个 EF 生成的模型创建转换器类。这似乎是最好的方法,这样每个 DBMS 都可能有自己的模型,但我的代码将处理映射。但在这样做的过程中,我真正从 EF 中获得了什么?也许查询生成,但这值得吗?
0 投票
2 回答
329 浏览

asp.net-mvc - 如何在不了解持久性的情况下进行单元测试

我正在开展一个新项目,我正在积极尝试尊重持久性无知。例如,在我的服务层中,我从 ORM 中检索一个实体,然后调用在实体上定义的例程,该例程可能会或可能不会对实体进行更改。然后我依靠我的 ORM 来检测实体是否被修改并进行必要的插入/更新/删除。

当我运行该应用程序时,它按预期工作,并且看到它在运行中真的很整洁。我的业务逻辑非常孤立,我的服务层非常薄。

当然,现在我正在添加单元测试,我注意到我不能再编写单元测试来验证某些属性是否被修改。在我之前的解决方案中,我确定是否对处于预期状态的对象进行了存储库调用。

我是否正确地接近持久性无知?当我没有显式调用存储库的保存方法时,是否有更好的方法来对我的实体的操作后状态进行单元测试?

如果有帮助,我正在使用 ASP.NET MVC 3、WCF、NHibernate 和 NUnit/Moq。我的单元测试通过我的服务类的实例(使用模拟存储库实例化)调用我的控制器操作。

0 投票
1 回答
357 浏览

entity-framework - 用于 POCO 的 EF 中的自定义数据访问

我目前正在编写一个 WCF 数据服务,该服务旨在以预定义的标准结构从任何数据库中提取数据。

我正在考虑使用 POCO 实体。我可以在 EF 设计器上设计我的实体并从中生成 POCO 类,但我很难理解的是如何编写数据访问层并将其注入 DBContext。

因此,对于每个不同的数据库,我将有一个数据访问层,该层将从数据库甚至 xml 文件中检索数据并将数据映射到我的 POCO 实体。

我不确定这是否可以实现。

POCO 课程将是我向世界公开的标准结构。我看不到任何地方可以编写自定义 sql 查询以从数据库中提取数据,然后在 POCO 类中设置数据。POCO 类与任何数据库表都不匹配,因此我明确需要将数据库字段映射到 POCO 类,但我不确定如何在使用 POCO 的实体框架中执行此操作。

我相信 POCO 是写选项,但在数据访问层和从数据库到 POCO 类的映射方面很挣扎。

我看到的所有示例都在谈论将 EF 直接连接到现有数据库。这意味着 EF 结构必须与数据库的结构相匹配。我想要的是一个可以从多个数据库中检索数据的单一 EF/POCO 结构。这些数据库的结构不同,但我需要手动从这些数据库中检索数据并将其转换为 POCO 类结构。我不一定想一次从多个数据库中获取数据,而是从单个数据库中获取数据,但想对任何数据库使用相同的模型 - 所以我想我必须为每个从数据库获取数据的数据库编写一个自定义 DAL 和将数据转换为 POCO 模型结构。

如果有人可以帮助我,我将不胜感激。

顺便说一下,我是 EF 的新手,所以请耐心等待。

0 投票
1 回答
170 浏览

wcf - EF4.x 和 WCF 服务(Persistence ignorant)更新具有 1 到 n 和 m 到 n 关系的嵌套实体。

我有 SQL Server 数据库,想使用 LINQ to Entities 并用 WCF 层包装它并将其公开给客户端。(典型的 N 层架构)。还希望有 Persistence ignorant 选项,并且还希望有一个选项忽略数据库中的某些字段(敏感信息)以将其序列化到客户端。

那么,使用具有持久性无知、具有 WCF 支持的自我跟踪的实体框架的最佳方法是什么。我可以找到带有 Self Tracking 或 Persistence Ignorant 的 T4 模板。但所有内容都捆绑为单个包。

对此的任何帮助将不胜感激。

0 投票
0 回答
43 浏览

architecture - 持久性无知的报告策略

我需要有关报告策略的建议。我们目前使用 Crystal Reports,但这在这里可能无关紧要……如果技术选择是问题,我们可以使用不同的东西。

我正在构建一个可以处理相当复杂的发票的应用程序,但归根结底,它们都是GetTotals. 持久性无知进展顺利,我正在隔离测试,以后可以存储所有内容。

但现在说我要报告发票总额。生成这些总数是应用程序的一部分,而不是数据库。我不想在数据库中复制该逻辑。过去,我会从一开始就将发票逻辑构建到数据库中,但这迫使我在应用程序方面采用相当脆弱的策略。

我该如何解决这个冲突?

谢谢你的建议,

——伊桑·尼尔森

0 投票
1 回答
1196 浏览

php - 加载文件或 blob 的域驱动设计方法?

我试图保持我的实体持久性和服务无知,但是当涉及到实体的 BLOB 和文件对应属性时,我遇到了障碍。假设我在聚合中有一个像这样的实体(例如保持基本):

我已经考虑或正在考虑的方法:

  1. 创建一个服务接口,'FileProvider' 或类似的方法load (Attachment $file),其实现者知道如何获取和返回文件的二进制文件
    • 这允许数据访问逻辑的多种实现(FileProviderMysql、FileProviderDirectory、FileProviderRemoteFTP 等)
    • 这似乎符合 Eric Evans 将服务类描述为封装了似乎不适合实体或值对象的行为的对象
    • 在 Evans 的书中也有示例,其中服务类使用简化的、意图揭示的接口封装对笨拙或遗留接口的访问
  2. 可能将所述接口的实现注入实体本身,以便可以使用与其任何其他属性相同的语法即时获取实体的内容
    • 这样,聚合的存储库(或其当前策略)将能够注入与当前存储实现相对应的服务实现,从而使客户端和应用程序服务免于进行该调用
    • 但是,我不确定实体是否应该真正“了解”服务接口

在这种情况下有经验的人可以权衡一下并帮助我做出决定吗?我想确保我正在做的工作能够坚持下去。谢谢...

0 投票
4 回答
4059 浏览

persistence - 持久性无知和 DDD 现实

我正在尝试不费吹灰之力地实现完全有效的持久性无知。不过我有很多问题:

最简单的选择

这真的很简单——可以像在 SOA 中那样使用 Spring Data 注释对实体进行注释(但让它们真正执行逻辑)?除了必须在实体中使用持久性注释之外还有什么后果,这并不真正遵循 PI 原则?我的意思是 Spring Data 真的是这样 - 它提供了很好的存储库,可以完成 DDD 中的存储库应该做的事情。问题在于实体本身......

更难的选择

为了使实体不知道它所操作的数据来自何处,很自然地通过构造函数将该数据作为接口注入。另一个优点是我们总是可以执行延迟加载——例如,我们在 Neo4j 图形数据库中默认拥有。缺点是聚合(由实体组成)将完全了解所有数据,即使它们不使用它们 - 由于数据完全暴露,可能会导致调试困难(DAO 将像聚合一样是分层的)。这也将迫使我们为存储库使用一些适配器,因为它们不再存储真实的实体......而且任何翻译都很丑陋......另一件事是我们无法在没有这样的 DAO 的情况下实例化实体 - 尽管可能存在-域中的内存实现......再次,更多层。

最难的选择

实体可以包裹在一个决定数据应该来自哪里的延迟加载器上。它可以是内存中的,也可以是数据库中的,它可以处理任何需要事务的操作等等。虽然是复杂的层,但在某种程度上可能是通用的......?在这里阅读

你知道其他解决方案吗?或者,也许我在提到的那些中遗漏了一些东西。请分享你的想法!

0 投票
1 回答
288 浏览

design-patterns - 使用 SQL(没有 ORM)可以实现什么级别的持久性无知?

在处理现有/遗留数据库时,似乎有一个共识,即 ORM 与普通 SQL/SQL 映射器相比并不是一个好的选择。例如,查看此处此处

我刚刚开始在针对遗留数据库的业务密集型应用程序上使用 MyBatis,但由于缺乏 ORM 功能(例如更改跟踪),我开始在我的存储库中编写更新函数,这些函数将尝试更新域实体及其直接关联。但这使得更新语句显着变慢!

因此,我们现在正在考虑为以下每种情况实现功能的新策略:更新实体的直接属性(例如:employeesRepository.update(employee)),更新实体的关联(例如:employeesRepository.updateEmployeeDepartment(employee))或更新实体的集合(例如:userRepository.updateUserRoles(user))。通过遵循此策略,每次更改业务逻辑时,都需要确保保留更改。

这里的主要问题是:在使用普通 SQL 或 MyBatis 等 SQL 映射器时,您可以在多大程度上实现对持久性的无知?实施变更跟踪机制以实现优化更新和清理存储库是否值得?

我还想知道是否有更好的策略将我的域模型映射到遗留数据库?

==============================

更新

为什么坚持无知?出于所有充分的理由。查看:持久无知有什么好处?例如。可测试性和可重用性是首先想到的事情。有关持久性无知及其好处的更多信息:msdn.microsoft.com/en-us/magazine/dd882510.aspx。

基本上我的代码目前看起来像这样:

如您所见,尽管数据访问逻辑和业务逻辑似乎是分开的,但我的数据访问逻辑知道我的域对象的状态究竟发生了什么变化。假设我需要在同一个promoteToDean函数中将员工的前缀更新为“Dean”,然后,除了facultyRepository.updateRoles(prof);我还必须添加类似:facultyRepository.updateTitle(prof);等等。然而,这些都是简单的场景,想象一下代码会如何看起来像复杂的用例。

http://msdn.microsoft.com/en-us/magazine/dd882510.aspx

0 投票
3 回答
458 浏览

domain-driven-design - 在域层中暴露 IUnitOfWork 接口违反了持久性无知规则?

1)在大多数情况下,每个都Aggregate Root应该定义自己的事务边界,在这种情况下,我们不需要IUnitOfWorkDomain Layer.

a)我假设在这种情况下,一个好的选择是让repository(用于aggregate强制invariants在其中应用)包含它自己的实例UoW(如果使用 EF,那么这个UoW实例可能只是类型DbContext)?

2)

a)但是如果出于某种原因transaction跨越多个aggregates(因此一次aggregate需要更改多个),那么是否也不Domain Layer需要包含IUnitOfWork接口?

IUnitOfWorkb) 暴露接口不会Domain Layer违反持久性无知规则吗?

c) 如果b)是,那么暴露IUnitOfWork的目的不就失败了repositories吗?

回复阿列克谢·拉加:

1) I would advice against exposing repositories to aggregates. Repositories are there to give you aggregates, that's it.

a)虽然我认为大多数 ddd 架构师在将 repos 暴露给聚合时没有问题(我只是问,因为我阅读了几篇关于 repos 和 DDD 的文章,我得到的印象是作者不反对暴露 repos聚合 - 但现在我不再那么确定了)?

b)所以您也反对将存储库暴露给域服务?

c)从你的回答来看,我猜你认为暴露IUnitOfWork是违反 PI 的?

2)Note that although my command handler (app service in a way)...

您通常将命令处理程序实现为应用服务吗?

3)

property.Approve(...)一个错字,你的意思是order.Approve(...)

提前感谢