2

どんな種類の助けも大歓迎です。(あなたの経験に基づいて)そのような巨大な階層にORMを使用するのは正気ではないと言うことができます:)。

背景 私のモデル レイヤーにはかなり大きなクラス階層があります。つまり、約 200 のクラスがあります。階層の良い点/悪い点は、それらのすべてが同じ基本クラスを持つことです。ベース クラスとリーフ クラスの間の最大距離は 7 で、階層内の任意のレベルの最大数のクラスは 80 です。nHibernate を使用して、永続ストレージからデータを保存/ロードしています。

問題 nHibernate によって生成されたクエリはかなり効率的です。たとえば、基本クラスのプロパティのフィルターに基づいてオブジェクトの ID を選択したい場合、NHibernate は、サブクラスごとのテーブルまたはクラスごとのテーブルなど、どのマッピング戦略を選択するかに応じて、階層内のすべてのテーブルを結合/結合しようとします。階層。

関連するすべてのテーブルをスキャンできるようになるまで、nHibernate はどのタイプのオブジェクトであるかを理解していません。しかし、現時点で基本クラスのデータだけに関心があるとしたらどうでしょう。nHibernate に基本クラス オブジェクトのみをロードさせる方法。

私の問題を説明するために、ここに簡略化されたバージョンがあります

public class Vehicle
{
    public virtual Guid Identifier { get; set; }
    public virtual int WheelsCount { get; set; }
    public virtual Make Make { get; set; }
    public virtual Model Model { get; set; }
}

public class Bike : Vehicle
{
    public Bike()
    {
        WheelsCount = 2;
    }

    public virtual bool IsDirtBike { get; set; }
}

public class Car : Vehicle
{
    public Car()
    {
        WheelsCount = 4;
    }

    public virtual bool IsFourWheelDrive { get; set; }

    public virtual string Title { get; set; }
    public virtual string Description { get; set; }
}

public class Make
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Model> Models { get; set; }
}

public class Model
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual Make Make { get; set; }
}

そして、マッピングは次のとおりです

public class VehicleMap : ClassMap<Vehicle>
{
    public VehicleMap()
    {
        Id(x => x.Identifier).GeneratedBy.Guid();
        Map(x => x.WheelsCount);

        References(x => x.Make).Column("MakeId");
        References(x => x.Model).Column("ModelId");

        Table("Vehicle");
        Polymorphism.Explicit();
        UseUnionSubclassForInheritanceMapping();
    }
}

public class BikeMap : SubclassMap<Bike>
{
    public BikeMap()
    {
        Map(x => x.IsDirtBike);
        Table("Bike");
        // Abstract();
    }
}

public class CarMap : SubclassMap<Car>
{
    public CarMap()
    {
        Map(x => x.Title);
        Map(x => x.Description);
        Map(x => x.IsFourWheelDrive);
        Table("Car");
       // Abstract();
    }
}

public class MakeMap : ClassMap<Make>
{
    public MakeMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        HasMany(x => x.Models)
            .KeyColumn("MakeId");
        Table("Make");
    }
}

public class ModelMap : ClassMap<Model>
{
   public ModelMap()
   {
       Id(x => x.Id);
       Map(x => x.Name);
       References(x => x.Make)
           .Column("MakeId");
       Table("Model");
   }
}

次のクエリを実行して四輪車をロードすると、NHibernate は vehicle、car、bike テーブルを結合します。今必要なのは Vehicle テーブルに保存されているデータだけです

List<Vehicle> vehicles = session.Query < Vehicle > ().Where(v => v.WheelsCount > 2).ToList();

車/バイクの代わりに車両オブジェクトのみを返すことができる場合、nHibernateに現在必要なデータを強制的にロードする方法を知っている人はいますか? スキーマにいくつかのテーブルがあるだけで、nHibernate によるこれらのクエリを見逃す可能性がありますが、200 個のテーブルがあると本当に困ります :(.

PS モデルに不具合がある場合は無視してください。これは実際のモデルではありません。前述のように、実際のモデルははるかに大きいです。このモデルは、問題を説明するためにあります。

4

1 に答える 1

2

Hibernate はテーブルを結合して、返すタイプを決定する必要があります。そうしないと、ポリモーフィズムが壊れてしまいます。また、抽象基底クラスなどのエッジのケースを処理するのははるかに困難です。

必要なプロパティのみを投影すれば、準備完了です

var vehicledatas = session.Query<Vehicle>()
    .Where(v => v.WheelsCount > 2)
    .Select(v => new { v.Id, v.WheelCount, v.Price })
    .ToList();

絶対に基本クラスのみが必要な場合は、このユースケース用に個別にマップしてください

public class AlternateVehicleMap : VehicleMap
{
    public AlternateVehicleMap()
    {
        EntityName("IAbsolutlyWantOnlyTheBaseClass");
        Readonly();   // to make sure noone messes up
    }
}

List<Vehicle> vehicles = session.CreateCriteria<Vehicle>("IAbsolutlyWantOnlyTheBaseClass").Add(Expression.Gt("WheelsCount", 2).List<Vehicle>();
于 2013-10-01T09:13:33.733 に答える