C# 使用存储库模式抽象出特定于数据库的id:s?
我正在学习DDD(域驱动设计)和存储库模式(C#)。我希望能够使用repository模式来持久化实体,而不关心实际使用的是哪个数据库(Oracle、MySQL、MongoDB、RavenDB等)。但是,我不确定如何处理数据库使用的特定于数据库的id:s most(all?)数据库。例如,RavenDB要求它应该存储的每个实体都有一个string类型的id属性。其他可能需要int类型的id属性。由于不同的数据库对其处理方式不同,因此我无法将数据库id作为实体类的一部分。但它必须存在于某个时刻,至少在我存储实际实体时是如此。我的问题是这方面的最佳实践是什么C# 使用存储库模式抽象出特定于数据库的id:s?,c#,database,domain-driven-design,repository,C#,Database,Domain Driven Design,Repository,我正在学习DDD(域驱动设计)和存储库模式(C#)。我希望能够使用repository模式来持久化实体,而不关心实际使用的是哪个数据库(Oracle、MySQL、MongoDB、RavenDB等)。但是,我不确定如何处理数据库使用的特定于数据库的id:s most(all?)数据库。例如,RavenDB要求它应该存储的每个实体都有一个string类型的id属性。其他可能需要int类型的id属性。由于不同的数据库对其处理方式不同,因此我无法将数据库id作为实体类的一部分。但它必须存在于某个时刻,至
我目前的想法是,对于我想要支持的每个数据库,为每个业务对象类型实现特定于数据库的“值对象”。然后,这些值对象将具有特定于数据库的id属性,我将在读写时在这两者之间进行映射。这似乎是个好主意吗?您可以在实体中潜在地拥有ID,但不能将其作为实体公共接口的一部分公开。这在NHibernate中是可能的,因为它允许您将表列映射到私有字段 所以你可能会有
class Customer {
private readonly Int32? _relationalId;
private readonly String? _documentId;
...
这并不理想,因为您的持久性逻辑会在业务逻辑上“出血”,但考虑到需求,它可能比在实体外部某处维护实体与其id之间的映射更容易、更健壮。我还强烈建议您评估“数据库不可知”方法,如果您只想支持关系数据库,这种方法会更现实。在这种情况下,您至少可以在存储库实现中重用类似NHibernate的ORM。大多数关系数据库支持相同的id类型。在您的场景中,您不仅需要ORM,还需要类似“对象文档映射器”的东西。我可以看出,您将不得不编写大量的基础架构代码。我强烈建议您重新评估您的需求,并在关系数据库和文档数据库之间进行选择。阅读此文:这是泄漏抽象的典型案例。您不可能在存储库接口下抽象出数据库的类型,除非您想去掉每个数据库附带的所有优点。对ID类型(字符串、Guid或其他)的要求只是巨大冰山的最顶端,其大部分质量都在浑水下 考虑事务处理、并发性和其他方面。我理解你关于坚持和无知的观点。当然,在域模型中不依赖于特定的数据库技术是一件好事。但是您也无法摆脱对任何持久性技术的依赖 让您的域模型与任何RDBMS一起工作都相对容易。其中大多数都有标准化的数据类型。使用像NHibernate这样的ORM将对您有很大帮助。在NoSQL数据库中实现相同的功能要困难得多,因为它们往往差异很大(这实际上非常好) 因此,我的建议是,对您必须处理的一组可能的持久性技术进行一些研究,然后为持久性子系统选择适当的抽象级别
如果这对您不起作用,请考虑活动来源。事件存储是要求最低的持久性技术之一。使用Jonathan Oliver之类的库将允许您使用几乎任何存储技术,包括文件系统。我将继续在实体中创建一个int-Id字段,然后将其转换为存储库中的字符串,其中Id必须是字符串。我认为抽象持久性的努力是非常值得的,而且实际上可以简化维护
然后,数据库可以持久化对象的约束已从“必须能够具有xxxx类型的主键”更改为简单的“必须能够存储xxxx类型”。我想你会发现你可以使用世界上任何一个数据库。快乐编码!DDD是最好的 你真的需要它吗?对我来说似乎不是个好主意,因为你会遇到维护地狱。我也面临同样的问题。不幸的是,这里提到的所有解决方案都没有让我觉得是“完美的解决方案”(如果有的话…)。我还考虑在数据抽象层中强制转换到特定的实现类型。我的意思是,虽然
DTO
s和DAO
s是所有数据库类型的通用接口,但任何特定的DAO
实现都会将其方法中的DTO
强制转换为相同的特定实现类型(我假设一次只使用一种数据库类型)。通过这种方式,它将能够使用特定的ID。它看起来很脏,但这是迄今为止我想到的最好的。我刚刚发现了另一个关于类似问题的问题,有一个答案似乎在这里也适用。看一看:不,这是相反的-一个避免泄漏抽象的经典案例。使用商店的ID类型作为对象的全局“友好”引用是有漏洞的。让商店坚持使用ID很好&通常是必要的。通常这两件事会很好地吻合。这家伙想把两者分开,所以他必须解决这个问题。@Chalky,我同意你的看法