0

データベース全体をエクスポート/インポートするのに役立つロジックを記述できる必要があります。もちろん、これを行うときはIDを無視する必要があるため、データをエクスポートしてからインポートすると、グラフ全体が複製されます。

アイデアは、カスタム コードを使用せずに単純なバイナリ シリアル化を使用することでした。そのため、必要なオブジェクトのグラフをシリアル化できます。しかし、私はNHibernateの問題に立ち止まりました。

問題は、このグラフには、単一の永続オブジェクトの実際には異なるオブジェクト (異なる参照) である多くのオブジェクトが含まれていることです。グラフが非常に複雑で、アプリケーション全体をやり直す必要があるため、これを修正するのは非常に困難です。だから私はこれと一緒に生きなければなりません。

すべてのグラフをファイルに保存してから逆シリアル化し、そのまま DB に保存しようとすると、これらのオブジェクトにはいくつかの ID が割り当てられるため、NHibernate はおそらく失敗します。IDをクリアする必要があります。しかし、これを行うと、NHibernate は各オブジェクトの ID を認識しなくなるため、すべてのオブジェクトは一時的なものであり、もちろん同じではありません。

例:

私は持っていUser {Id = 3} ますMail {Id = 2, with User(Id = 3)}

ここの 2 人のユーザーは同じ ID を持っているため、同じです。しかし、参照は等しくありません。このグラフの ID をクリアすると、両方のユーザーが参照が等しくないため、異なるオブジェクトになります。

私は考えていました-オブジェクトにID(!= 0)がありますが、それらは一時的なものであり、DBに挿入する必要があり、新しいIDを受け取る必要があることをNHibernateに伝えることができますか?または、私の問題を解決する別の方法を知っているかもしれません。

PS すべてのオブジェクトは切り離されています - それらが永続的であると言うとき、私はそれらが Id != 0 を持ち、エクスポートする前に DB にコピーを持っていたことを意味します (別の DB であった可能性があります)

アップデート

作業したいコードの例を追加しました。最終的な呼び出しでは、SaveOrUpdate実行ごとに 1 つのオブジェクトを挿入する必要があります。実際のコードはもう少し複雑ですが、s1 と s2 を含む単一の階層 (単一の永続オブジェクトを表す 2 つの異なるオブジェクト。それらの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 に答える