FluentNHibernate SubClassMap 问题:鉴别器失败

发布于 2024-11-26 17:01:14 字数 3326 浏览 2 评论 0原文

我有一个非常简单的问题,但现在似乎看不到重点。 我的目的是读取 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); }
}

我故意省略了 ID 和其他属性以保持可读性。如果你按原样运行它,它将无法编译。

实际发生的情况是,所有车辆都被加载到任一集合中,因此 - 据我了解 - 鉴别器被忽略了。

你知道我在这里可能遗漏了什么/做错了什么吗?

编辑:我刚刚运行了一个 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(请注意,鉴别符被放置为静态字符串by 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) Selecting

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(为什么这里没有鉴别器?生成的第一个 select 语句中的 @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

I have a pretty simple problem, but right now can't seem to see the point.
My intention is to read a List of VehicleCollector objects, each one with a neat list of Cars and another list of Trains. Vehicles come from a single table and are discriminated by a column named TYPE.

Model Code:

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 { }

Mapping Code:

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); }
}

I left out IDs and other properties intentionally to keep this readable. It won't compile if you run it the way it is.

What actually happens is that all vehicles are loaded into either one of the collections, so - to my understanding - the discriminator has been neglected.

Do you have any idea what I might be missing / doing wrong here?

EDIT: I just ran a SchemaExport to SQLite to see how this behaves. Here's some more detail on what's happening - step by step. Note : Some properties may have changed / been added.

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) Inserting

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);

This results in the following SQL (Note that the discriminators are placed as static strings by 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) Selecting

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);

This results in the following SQL (Why are there no discriminators here? And what is @p1 in the first select statement generated for?):

 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;

Obivously, NHibernate 2.1 has trouble selecting using the discriminator, while inserting works as intended. Any fresh ideas?

TIA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

惜醉颜 2024-12-03 17:01:14

我遇到过类似的情况(如果不一样),其中选择内容不起作用,因为它不包含任何鉴别器信息。要强制始终包含鉴别器信息,请添加以下内容:

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

这将强制将鉴别器信息包含在查询中。

I've had something similar (if not the same) where selecting things wasn't working because it wasn't including any of the discriminator information. To force discriminator information to ALWAYS be included, add this:

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

This will force discriminator information to be included in queries.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文