1

NHibernate の使用: 3.3.2 Fluent NHibernate: 1.3.0 .NET 4.0

こんにちは、自動マッピング、特にテーブルごとの階層継承の設定を使用して、Fluent NHibernate の (非常に) 単純な参照プロジェクトをまとめようとしています。既存の(作業中の)プロジェクトから構成をコピーしようとしましたが、AutoMapping と継承に関する Fluent Wiki ページの例を実行しましたが、どちらも同じ結果が得られました。table-per-hiarchy で設定した基本クラスは、通常のクラスのように扱われます。

ドメイン モデルは次のようになります。

namespace Tests
{
    public abstract class Animal
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual int Legs { get; set; }
    }

    public class Cat : Animal {}

    public class Budgie : Animal {}
}

私が言ったように、簡単に、継承を説明するだけです。「脚」はおそらく基本クラスでオーバーライドする必要があることを認識しています:)

AutoMapping 構成は次のようになります。

public class AutoMappingConfig : DefaultAutomappingConfiguration
{
    public override bool ShouldMap(Type type)
    {
        var include = type.IsSubclassOf(typeof(Animal));
        Debug.WriteLineIf(include, string.Format("Included {0} in NHibernate mapping.", type));
        return include;
    }

    public override bool IsDiscriminated(Type type)
    {
        var result = type.In(
            (typeof(Cat)),
            (typeof(Budgie))
            );

        return result;
    }
}

最後に、構成/セッションの作成は次のようになります。

public static ISession NewSession()
{
    var cfg = new AutoMappingConfig();

    var map = AutoMap.AssemblyOf<Animal>(cfg)
        .IgnoreBase<Animal>();

    var dbConfiguration = MsSqlConfiguration.MsSql2008
        .ConnectionString(ConfigurationManager.ConnectionStrings["testdb"].ConnectionString);

    return Fluently.Configure()
        .Mappings(m =>m.AutoMappings.Add(map))
        .Database(dbConfiguration)
        .BuildSessionFactory()
        .OpenSession();
}

それをまとめて、いくつかの新しいレコードを作成しようとします。

[Test]
public void CreateData()
{
    var tiddles = new Cat {Name = "Tiddles", Legs = 4};
    var kylie = new Budgie {Name = "Kylie", Legs = 2};

    using (var transaction = _session.BeginTransaction())
    {
        _session.Save(tiddles); // exception!
        _session.Save(kylie);

        transaction.Commit();
        }
    }
}

エラーは次のとおりです。

NHibernate.Exceptions.GenericADOException : 挿入できませんでした: [Tests.Cat][SQL: INSERT INTO [Cat] (Name, Legs) VALUES (?, ?); SCOPE_IDENTITY() を選択] ----> System.Data.SqlClient.SqlException : 無効なオブジェクト名 'Cat'。

注意すべき点がいくつかあります。

  • 「?」SQL プロファイラーで確認すると、入力されています。
  • IsDiscriminated(Type type) メソッドにブレークポイントを配置すると、予想される 2 つのタイプ (Cat と Budgie) で呼び出され、毎回 true を返すことがわかります。ただし、SQL は間違ったテーブルに書き込んでおり、識別子列を書き込んでいません。つまり、これらのクラスは差別されていると言われていますが、そのように扱われていません。
  • 表の Id 列は、自動インクリメントの ID 列です。
  • 正しい動作をトリガーするために基本プロパティ以外のものが必要な場合に備えて、2 つのサブクラスに他のプロパティを追加しようとしました (違いはありません)。

どんな助けでも大歓迎です。私は今、それが明らかなことであると確信していますが、NHibernate についてよく知っている人は誰もいません (LightSpeed は別の問題です)。


わかりましたので、最終的な作業コードは次のようになります。

public class AutoMappingConfig : DefaultAutomappingConfiguration
{
    public override bool ShouldMap(Type type)
    {
        var include = type.IsSubclassOf(typeof(Animal)) || type == typeof (Animal);
        Debug.WriteLineIf(include, string.Format("Included {0} in NHibernate mapping.", type));
        return include;
    }

    public override bool IsDiscriminated(Type type)
    {
        return typeof(Animal).IsAssignableFrom(type);
    }
}

public static ISession NewSession()
{
    var cfg = new AutoMappingConfig();

    var map = AutoMap.AssemblyOf<Animal>(cfg)
        .IncludeBase<Animal>();

    var dbConfiguration = MsSqlConfiguration.MsSql2008
        .ConnectionString(ConfigurationManager.ConnectionStrings["testdb"].ConnectionString);

    return Fluently.Configure()
        .Mappings(m =>m.AutoMappings.Add(map))
        .Database(dbConfiguration)
        .BuildSessionFactory()
        .OpenSession();
}

そして、すべてが世界でうまくいっています:)

(つまり、3 つのエラーがありました)

ここでの説明は、最初に .IgnoreBase<> の使用について説明しているため、NHibernate はそれ自体でベースをエンティティとして扱わないため、後で抽象レイヤーのスーパータイプを使用するときに .Includebase<> の使用について言及しているため、少し混乱しています。どちらも試してみたが、フィーロの答えがなければうまくいかなかった。

4

1 に答える 1

0

あなたは動物を忘れました

public override bool IsDiscriminated(Type type)
{
    return typeof(Animal).IsAssigneableFrom(type);
}
于 2012-11-13T20:49:57.253 に答える