FluentNHibernate SubClassMap Проблема: сбой дискриминатора - PullRequest
2 голосов
/ 29 июля 2011

У меня довольно простая проблема, но сейчас, похоже, не вижу смысла.Мое намерение состоит в том, чтобы прочитать список объектов VehicleCollector, каждый из которых содержит аккуратный список автомобилей и еще один список поездов.Транспортные средства поступают из одной таблицы и различаются по столбцу с именем TYPE.

Код модели:

public class VehicleCollector
{
    public virtual IList<Car> Cars { get; set; }
    public virtual IList<Train> Trains { get; set; }
}

public class Vehicle { }

public class Car : Vehicle {}

public class Train : Vehicle { }

Код отображения:

public class FooMap : ClassMap<VehicleCollector>
{
    public FooMap()
    {
        this.HasMany(x => x.Cars).KeyColumn("foo_id");
        this.HasMany(x => x.Trains).KeyColumn("foo_id");
    }
}

public class VehicleMap : ClassMap<Vehicle>
{
    public VehicleMap() { this.DiscriminateSubClassesOnColumn("type"); }
}

public class CarMap : SubclassMap<Car>
{
    public CarMap() { this.DiscriminatorValue(1); }
}

public class TrainMap : SubclassMap<Train>
{
    public TrainMap() { this.DiscriminatorValue(2); }
}

Я пропустил идентификаторы идругие свойства намеренно, чтобы сохранить это читаемым.Он не скомпилируется, если вы запустите его таким, какой он есть.

На самом деле происходит то, что все транспортные средства загружены в одну из коллекций, поэтому, насколько я понимаю, дискриминатором пренебрегли.

Есть ли у вас какие-либо идеи о том, что я могу упустить / сделать здесь неправильно?

РЕДАКТИРОВАТЬ: Я просто запустил SchemaExport для SQLite, чтобы посмотреть, как это происходит.Вот еще несколько подробностей о том, что происходит - шаг за шагом.Примечание. Некоторые свойства могут быть изменены / добавлены.

1) SchemaExport

 create table vehicle_collector
 (
    id INTEGER not null,
   name TEXT not null,
   primary key (id)
);

create table vehicle (
    id INTEGER not null,
   desc TEXT not null,
   type TEXT not null,
   collector_id INTEGER,
   primary key (id)
);

2) Вставка

VehicleCollector c = new VehicleCollector() { Id = 1001, Name = "foobar" };
Train v2 = new Train() { Id = 101, desc = "Foo" };
Car v1 = new Car() { Id = 102, desc = "Bar" };
c.Cars.Add(v1);
c.Trains.Add(v2);
openSession.Save(c);

Это приводит к следующему SQL (обратите внимание, что дискриминаторы помещаются как статические строки NHibernate):

INSERT INTO vehicle_collector (name, id) VALUES (@p0, @p1); @p0 = 'foobar', @p1 = 1001;
INSERT INTO vehicle (desc, type, id) VALUES ( @p1, '2', @p2); @p1 = 'Foo', @p2 = 101;
INSERT INTO vehicle (desc, type, id) VALUES ( @p1, '1', @p2); @p1 = 'Bar', @p2 = 102;
UPDATE vehicle SET collector_id = @p0 WHERE id = @p1; @p0 = 1001, @p1 = 101;
UPDATE vehicle SET collector_id = @p0 WHERE id = @p1; @p0 = 1001, @p1 = 102;

3) Выбор

VehicleCollector v1 = openSession.CreateCriteria<VehicleCollector>()
                                    .Add(Restrictions.Eq("Id", 1001L))
                                    .SetMaxResults(1)
                                    .List<VehicleCollector>()
                                    .First();
Assert.AreEqual(1, v1.Cars.Count);
Assert.AreEqual(1, v1.Trains.Count);

Это приводит к следующему SQL (почему здесь нет дискриминаторов? И что такое @ p1 в первом операторе выбора, сгенерированном для?):

 SELECT this_.id as id0_0_, this_.name as name0_0_
   FROM vehicle_collector this_
  WHERE this_.id = @p0 limit 1;
 @p0 = 1001, @p1 = 1;

 SELECT vehicle0_.collector_id as collector5_1_,
        vehicle0_.id        as id1_,
        vehicle0_.id        as id1_0_,
        vehicle0_.desc      as desc1_0_
   FROM vehicle vehicle0_
  WHERE vehicle0_.collector_id = @p0;
 @p0 = 1001;

Очевидно, что NHibernate 2.1 имеет проблемы с выбором, используя дискриминатор, при вставке работает как задумано.Есть свежие идеи?

TIA

1 Ответ

2 голосов
/ 02 августа 2011

У меня было нечто подобное (если не то же самое), когда выбор вещей не работал, потому что он не включал в себя какую-либо информацию дискриминатора.Чтобы принудительно включить информацию дискриминатора в ВСЕГДА, добавьте:

this.DiscriminateSubClassesOnColumn("type").AlwaysSelectWithValue();

Это заставит информацию дискриминатора быть включенной в запросы.

...