0

nhibernate を使用した古い大きな asp.net アプリケーションがあり、その一部を拡張およびアップグレードしています。使用されていた NHibernate はかなり古い (1.0.2.0) ため、新しい機能のために (2.1.2) にアップグレードすることにしました。HBM ファイルは、MyGeneration を使用してカスタム テンプレートを介して生成されます。1つのことを除いて、すべてが非常にスムーズに進みました。

Blog と Post をオブジェクトにする必要があるとしましょう。ブログには多数の投稿を含めることができるため、Post は多対 1 の関係になります。このアプリケーションの動作方法により、リレーションシップは主キーではなく、Blog.Reference 列を介して行われます。

サンプル マッピングと .cs ファイル:

<?xml version="1.0" encoding="utf-8" ?>

    <id name="Id" column="Id" type="Guid">
        <generator class="assigned"/>
    </id>
    <property column="Reference" type="Int32" name="Reference" not-null="true" />
    <property column="Name" type="String" name="Name" length="250" />
</class>

<?xml version="1.0" encoding="utf-8" ?>

    <id name="Id" column="Id" type="Guid">
        <generator class="assigned"/>
    </id>

    <property column="Reference" type="Int32" name="Reference" not-null="true" />
    <property column="Name" type="String" name="Name" length="250" />
    <many-to-one name="Blog" column="BlogId" class="SampleNamespace.BlogEntity,SampleNamespace" property-ref="Reference" />
</class>

そしてクラスファイル

class BlogEntity
{
    public Guid Id { get; set; }
    public int Reference { get; set; }
    public string Name { get; set; }
}

class PostEntity
{
    public Guid Id { get; set; }
    public int Reference { get; set; }
    public string Name { get; set; }
    public BlogEntity Blog { get; set; }
}

ここで、ID が 1D270C7B-090D-47E2-8CC5-A3D145838D9C で参照 1 のブログがあるとします。

古いnhibernateでは、そのようなことが可能でした:

        //this Blog already exists in database
        BlogEntity blog = new BlogEntity();
        blog.Id = Guid.Empty;
        blog.Reference = 1; //Reference is unique, so we can distinguish Blog by this field
        blog.Name = "My blog";

        //this is new Post, that we are trying to insert
        PostEntity post = new PostEntity();
        post.Id = Guid.NewGuid();
        post.Name = "New post";
        post.Reference = 1234;
        post.Blog = blog; 

        session.Save(post);

しかし、新しいバージョンでは、Post.BlogId に NULL を挿入できないという例外が発生します。私が理解しているように、古いバージョンでは、nhibernate の場合、Blog.Reference フィールドがあれば十分であり、そのフィールドでエンティティを取得して PostEntity にアタッチすることができ、PostEntity を保存すると、すべてが正しく機能しました。そして、私が理解しているように、新しい NHibernate は Blog.Id によってのみ取得しようとします。

これを解決するには?オブジェクトは制御できないため、DB の設計を変更したり、BlogEntity に ID を割り当てたりすることはできません (これらのオブジェクトは、外部ソースからこのような一般的な「オブジェクト」として事前に入力されています)。

4

3 に答える 3

0

コードが NH 1 で機能したことは非常に奇妙に思えます。しかし、とにかく現時点では機能していないため、まずクエリでブログ エンティティを探す必要があると思います。

var criteria = DetachedCriteria.For<Blog>();
criteria.Add(Expression.Eq("Reference", 1));
var blog = criteria.GetExecutableCriteria(session).List<Blog>().FirstOrDefault();

post.Blog = blog;
session.Save(post);
于 2010-05-18T18:45:11.030 に答える
0

これ

blog.Id = Guid.Empty

DB ではヌルとして変換されます。したがって、変更すると (サンプル コードが示すように)、明示的に BlogEntity Id に null 値を設定することになります。

これはあなたが受け取っているエラーであり、「参照」列/プロパティとは無関係です。

何ができるかという問題については...まあ、ORM を Guid に参加させる必要はありません! 参照列で結合を行うことができます...

于 2010-05-19T08:23:40.623 に答える
0

私自身の質問に答えます。

問題は、nhibernate が ID 00000000-0000-0000-0000-000000000000 の BlogEntity を取得するために DB にアクセスしていたことです。もちろんDBでは何も得られなかったので、nullを挿入しようとしました

そして、なぜそれが起こっていたのかは、ログにはっきりと表示されていました

割り当てられた識別子 00000000-0000-0000-0000-000000000000 を持つ BlogEntity が一時的なものか分離されたものかを判断できません。データベースのクエリ。これを防ぐには、セッションで明示的な Save() または Update() を使用します。

私の実装を解決し、IInterceptorそれを Session に渡し、特にそのメソッドbool? IsTransient(object entity)

そして問題は解決しました。

于 2010-06-10T15:09:56.593 に答える