0

我需要能够编写一个逻辑来帮助我导出/导入整个数据库。当然,这样做时应该忽略 id,所以如果我导出数据,然后导入它 - 应该克隆整个图。

这个想法是使用简单的二进制序列化而不需要任何自定义代码 - 所以我可以序列化任何我想要的对象图。但我在 NHibernate 问题上停了下来。

问题是该图包含许多对象,这些对象实际上是单个持久对象的不同对象(不同的引用)。由于图表非常复杂,因此很难解决这个问题,我需要为此重做整个应用程序。所以我必须忍受这个。

如果我只是将所有图形保存到文件中,然后对其进行反序列化并尝试按原样保存到 DB - 这些对象将分配一些 id,因此 NHibernate 可能会失败。我需要清除身份证。但是如果我这样做 - NHibernate 不再知道每个对象的身份,所以每个对象都是瞬态的,当然,是不相等的。

例子:

我有User {Id = 3}Mail {Id = 2, with User(Id = 3)}

这里的两个用户具有相同的 ID - 所以他们是平等的。但不是参考相等。当我清除此图的 ID 时 - 两个用户都成为不同的对象,因为它们不是引用相等的。

我在想——我能不能告诉 NHibernate,即使对象有 id(!= 0),但它们是瞬态的,应该插入到数据库中,它们应该接收新的 Id。或者,也许您知道解决我的问题的另一种方法。

PS所有对象都是分离的-当我说它们是持久的时,我的意思是它们具有Id!= 0并且在导出之前它们在数据库中具有副本(可能是另一个数据库)

更新

我添加了一个我想要工作的代码示例。最后的SaveOrUpdate调用应该每次运行都插入一个对象。实际的代码有点复杂,但问题是我有一个包含 s1 和 s2 的层次结构(两个不同的对象代表单个持久对象。它们的Equal() == true, but ReferenceEqual == false)我需要克隆它并保存它确保结果对象在数据库中是单一的。

        User s1;
        User s2;

        using (var session = DBHandler.GetSessionFactory().OpenSession())
        {
            s1 = session.Get<User>(1);
        }

        using (var session = DBHandler.GetSessionFactory().OpenSession())
        {
            s2 = session.Get<User>(1);
        }

        var c1 = (User)DBHandler.DeepClone(s1);
        var c2 = (User)DBHandler.DeepClone(s2);

        // These updates should insert only one object, because it is actually one object.
        using (var session = DBHandler.GetSessionFactory().OpenSession())
        {
            session.SaveOrUpdate(c1);
        }

        using (var session = DBHandler.GetSessionFactory().OpenSession())
        {
            session.SaveOrUpdate(c2);
        }
4

1 回答 1

0

与此处相同的概念证明

Configuration config;
ISessionFactory factory;

public object DeepClone(object original)
{

    var metadata = factory.GetClassMetadata(original.GetType());

    var clone = metadata.Instantiate(0 /*or extract unsaved value from config*/, EntityMode.Poco);

    var values = metadata.GetPropertyValues(original, EntityMode.Poco);

    for (int i = 0; i < metadata.PropertyTypes.Length; i++)
    {
        if (metadata.PropertyTypes[i].IsAssociationType && values[i] != null)
        {
            values[i] = DeepClone(values[i]);
        }
        if (metadata.PropertyTypes[i].IsCollectionType)
        {
            // TODO: Copy Collection
        }
    }
    metadata.SetPropertyValues(clone, values, EntityMode.Poco);

    return clone;
}
于 2013-06-06T09:33:44.967 回答