使用存储库模式抽象出数据库特定的 id:s?
我正在学习 DDD(领域驱动设计)和存储库模式(C# 中)。我希望能够使用存储库模式来持久化实体,而不关心实际使用哪个数据库(Oracle、MySQL、MongoDB、RavenDB 等)。但是,我不确定如何处理大多数(所有?)数据库使用的数据库特定 id:。例如,RavenDB 要求它存储的每个实体都有一个字符串类型的 id 属性。其他可能需要 int 类型的 id 属性。由于不同数据库对此的处理方式不同,因此我无法将数据库 ID 作为实体类的一部分。但它必须在某个时刻存在,至少当我存储实际实体时。我的问题是这方面的最佳实践是什么?
我当前追求的想法是,对于我想要支持的每个数据库,为每个业务对象类型实现数据库特定的“值对象”。这些值对象将具有数据库特定的 id 属性,我将在读取和写入时在两者之间进行映射。这看起来是个好主意吗?
I'm learning DDD (domain driven design) and the repository pattern (in C#). I would like to be able to use the repository pattern to persist an entity and not care which database is actually used (Oracle, MySQL, MongoDB, RavenDB, etc.). I am, however, not sure how to handle the database specific id:s most (all?) databases uses. RavenDB, for example, requires that each entity it should store has an id property of type string. Other may require an id property of type int. Since this is handled differently by different databases, I cannot make the database id a part of the entity class. But it would have to exist at some point, at least when I store the actual entity. My question is what the best practise regarding this is?
The idea I am currently pursuing is to, for each database I want to support, implement database specific "value objects" for each business object type. These value object would then have the database specific id property and I would map between the two upon reads and writes. Does this seem like a good idea?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是泄漏抽象的典型案例。您不可能在存储库接口下抽象出数据库的类型,除非您想放弃每个数据库附带的所有好东西。对 ID 类型(字符串、Guid 或其他)的要求只是巨大冰山的最顶端,其大部分质量都在浑水中。
考虑事务处理、并发性和其他东西。我理解你关于持久性无知的观点。不依赖于领域模型中的特定数据库技术肯定是一件好事。但您也无法摆脱对任何持久性技术的依赖。
让您的领域模型与任何 RDBMS 良好配合相对容易。其中大多数都有标准化的数据类型。使用像 NHibernate 这样的 ORM 会对你有很大帮助。在 NoSQL 数据库中实现相同的目标要困难得多,因为它们往往差异很大(这实际上非常好)。
因此,我的建议是对您必须处理的可能的持久性技术集进行一些研究,然后为持久性子系统选择适当的抽象级别。
如果这对您不起作用,请考虑事件溯源。事件存储是要求最低的持久性技术之一。使用 Jonathan Oliver 的 EventStore 等库将允许您使用几乎任何存储技术,包括文件系统。
This is the classic case of leaking abstractions. You can't possibly abstract away the type of database under a repository interface unless you want to loose all the good things that come with each database. The requirements on ID type (string, Guid or whatever) are only the very top of huge iceberg with majority of its mass under the muddy waters.
Think about transaction handling, concurrency and other stuff. I understand your point about persistence ignorance. It's a good thing for sure to not depend on specific database technology in the domain model. But you also can't get rid of any dependency on any persistence technology.
It's relatively easy to make your domain model work well with any RDBMS. Most of them have standardized data types. Using ORM like NHibernate will help you a lot. It's much harder to achieve the same among NoSQL databases because they tend to differ a lot (which is very good actually).
So my advise would be to do some research on what is the set of possible persistence technologies you will have to deal with and then choose appropriate level of abstraction for the persistence subsystem.
If this won't work for you, think about Event Sourcing. The event store is one of the least demanding persistence technique. Using library such as Jonathan Oliver's EventStore will allow you to use virtually any storage technology, including file system.
我将继续在实体中创建一个 int Id 字段,然后将其转换为存储库中的字符串,其中 Id 必须是字符串。我认为抽象你的持久性的努力是非常值得的,并且实际上简化了维护。
I would go ahead and create an int Id field in the entity and then convert that to a string in the repository where the Id must be a string. I think the effort to abstract your persistence is very worth while and actually eases maintenance.
您正在做正确的事情!让您摆脱数据库主键类型的限制!
不要尝试翻译类型,只需使用不同的字段。
具体来说:不要尝试使用数据库的主键,除非在数据访问逻辑中。如果您需要一个对象的友好 ID,只需创建一个附加字段(无论您喜欢什么类型),并要求您的数据库来存储它。仅在您的数据访问层中,您才需要查找&根据对象的友好 ID 更新数据库记录。简单的。
然后,对哪些数据库可以持久保存对象的限制已从“必须能够具有 xxxx 类型的主键”更改为简单的“必须能够存储 xxxx 类型”。我想你会发现你可以使用世界上任何数据库。快乐编码! DDD是最好的!
You are doing the right thing! Abstract yourself away from the constraints of the databases primary key types!
Don't try to translate types, just use a different field.
Specifically: Do not try to use the database's primary key, except in your data access logic. If you need a friendly ID for an object, just create an additional field, of whatever type you like, and require your database to store that. Only in your data access layer would you need to find & update the DB record(s) based on your object's friendly ID. Easy.
Then, your constraints on which databases can persist your objects have changed from 'must be able to have a primary key of type xxxx' to simple 'must be able to store type xxxx'. I think you'll then find you cna use any database in the world. Happy coding! DDD is the best!
您可以在实体中拥有 ID,但不能将其公开为实体公共接口的一部分。 NHibernate 可以实现这一点,因为它允许您将表列映射到私有字段。
因此,您可能会遇到类似的情况,
这并不理想,因为您的持久性逻辑会在业务逻辑上“渗透”,但考虑到需求,它可能比在实体外部的某个地方维护实体与其 id 之间的映射更容易、更健壮。我还强烈建议您评估“与数据库无关”的方法,如果您只想支持关系数据库,这种方法会更现实。在这种情况下,您至少可以在存储库实现中重用像 NHibernate 这样的 ORM。大多数关系数据库都支持相同的 id 类型。在您的场景中,您不仅需要 ORM,还需要诸如“对象文档映射器”之类的东西。我可以看到您将不得不编写大量的基础设施代码。我强烈建议您重新评估您的需求并在关系数据库和文档数据库之间进行选择。阅读本文:基于文档的数据库与关系数据库的优点/缺点数据库
You can potentially have the ids in the entity but not expose it as part of entity's public interface. This is possible with NHibernate because it allows you to map table column to a private field.
So you can potentially have something like
This is not ideal because your persistence logic 'bleeds' on business logic but given the requirements it probably is easier and more robust than maintaining mapping between entity and its id somewhere outside entity. I would also highly recommend you to evaluate "Database agnostic" approach which would be more realistic if you only want to support relational databases. In this case you can at least reuse ORM like NHibernate for your repository implementation. And most relational database support same id types. In your scenario you not only need ORM you also need something like "Object-Document-Mapper". I can see that you will have to write tons and tons of infrastructure code. I highly recommend you to reevaluate your requirements and choose between relational and document databases. Read this: Pros/cons of document-based databases vs. relational databases