我有一个桌面(winforms)应用程序,它使用Firebird数据库作为数据存储(在嵌入模式下),我使用NHibernate进行ORM。我们需要支持的功能之一是能够从外部文件导入/导出数据组。目前,此外部文件也是一个与主数据库具有相同模式的数据库。
我已经设置NHibernate来查看多个数据库,我可以同时使用两个数据库。但问题是在两个数据库之间复制数据。我有两个复制策略:(1)复制所有相同的ID对象[aka导入/导出]和(2)复制与大多数新ID [aka复制/复制]。我说“大多是新的”,因为有些查找项总是会被复制为相同的ID。
使用新ID复制所有内容很好,因为我只有一个“CopyForExport”方法可以创建所有内容的副本而不分配新ID(或清除对象树中的所有ID)。
在保持相同ID的同时,处理这种情况以及在数据库之间复制数据的“最佳实践”方法是什么?
澄清:我不是试图同步两个数据库,只是导出一个子集(用户可选)或数据传输给其他人(然后将数据子集导入他们自己的数据库)。
进一步澄清:我认为我已将问题分解为: 我想使用NHibernate的ISession.SaveOrUpdate特性,所以我用一个没有“赋值”的身份生成器来设置我的实体。但是,当我想覆盖生成的标识时(在同一进程中复制多个数据库之间的数据),我遇到了问题。
有没有办法使用Guid.Comb或UUID生成器,但有时可以指定我自己的标识符(用于传输到具有相同模式的不同数据库连接)。
答案 0 :(得分:13)
我找到了自己问题的答案: 关键是ISession.Replicate方法。这允许您在数据存储之间复制对象图并保持相同的标识符。要创建新的标识符,我想我可以使用ISession.Merge,但我仍然必须验证这一点。
但有几点需要注意:我的测试类有一个对父对象的引用(多对一关系),我不得不让类非延迟加载以使Replicate正常工作。如果我没有将它设置为急切加载(我猜是非延迟加载),它只会复制对象而不是父对象(我的hbm.xml文件中的cascade =“all”)。
java Hibernate文档引用了Replicate(),但NHibernate文档没有(java文档中的section 10.9)。
这对于复制行为是有意义的,因为我们希望在将它们传输到另一个数据存储之前具有完全水合的实体。但奇怪的是,即使两个会话都打开(每个数据存储一个会话),当我想要复制它时,它也不会考虑给对象加水。
答案 1 :(得分:0)
您可以使用FBCopy。只需定义要复制的表和列,我就可以完成这项工作。您还可以为每个表添加可选的WHERE子句,因此它只复制您想要的行。
复制时,确保维护导出数据的顺序,以便外键不会中断。它还支持生成器。