流利的NHibernate HasMany没有更新FK

时间:2022-12-10 11:35:23

I'm using latest Fluent NHibernate lib (0.1.0.452) and I have a problem with saving child entitites.

我正在使用最新的Fluent NHibernate lib(0.1.0.452),我在保存子权限方面遇到了问题。

I think this is rather common scenario... I've got a parent with mapping:

我认为这是相当常见的情况......我有一个父映射:

HasMany<Packet>(x => x.Packets)
            .Cascade.All()
            .KeyColumnNames.Add("OrderId");

and a simple Packet class that (in a domain model and FNH mapping) doesn't have any reference to the parent. What gets generated is a correct Packets table that contains a column named OrderId. What doesn't work is the saving. Whenever I try to save parent object, the children are also saved, but the FK stays untouched. I checked the SQL and in INSERT statement the OrderId doesn't even appear!

和一个简单的Packet类(在域模型和FNH映射中)没有对父进程的任何引用。生成的是一个正确的Packets表,其中包含一个名为OrderId的列。什么是行不通的是节约。每当我尝试保存父对象时,子节点也会被保存,但FK保持不变。我检查了SQL,在INSERT语句中,OrderId甚至没有出现!

INSERT INTO KolporterOrders (CargoDescription, SendDate, [more cols omitted] ) VALUES ('order no. 49', '2009-04-22  00:57:44', [more values omitted])
SELECT LAST_INSERT_ID()
INSERT INTO Packets (Weight, Width, Height, Depth) VALUES ('To5Kg', 1, 1, 1)
SELECT LAST_INSERT_ID()

As you see the OrderId is completely missing in the last INSERT.

如您所见,在上一次INSERT中完全缺少OrderId。

I also checked the generated NH mapping and it seems it's ok:

我还检查了生成的NH映射,看起来没问题:

<bag name="Packets" cascade="all">
    <key column="OrderId" />
    <one-to-many class="Company.Product.Core.Packet, Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bag>

I tried setting Cascade to different values. I even added References to the PacketMap (FNH mapping class).

我尝试将Cascade设置为不同的值。我甚至添加了PacketMap(FNH映射类)的引用。

Any ideas why the OrderId is not being inserted?

有没有为什么没有插入OrderId的想法?

Edit: forgot to mention: I'm using MySQL5 if it matters.

编辑:忘了提一下:如果重要的话,我正在使用MySQL5。

Edit2: The above FNH mapping generates hbm with bag (not a set) - I edited it. The C# code used for saving:

Edit2:上面的FNH映射生成hbm with bag(不是一组) - 我编辑了它。用于保存的C#代码:

var order = new Order(); 
NHSession.Current.SaveOrUpdate(order); //yes, order.Packets.Count == 1 here

///Order.cs, Order ctor
public Order()
    {
        CreateDate = DateTime.Now;
        OrderState = KolporterOrderState.New;
        Packets = new List<Packet>();
        Packets.Add(new Packet()
        {
            Depth = 1,
            Height = 1,
            Width = 1,
            Weight = PacketWeight.To5Kg
        });
    }

the session gets flushed and closed at EndRequest.

会话在EndRequest中刷新并关闭。

3 个解决方案

#1


Ok, my fault. I was testing it in ApplicationStart of global.asax, so the Request hadn't been created so the session wasn't flushed. I realised it when I tested it on a simple ConsoleApp project when I saw that flushing actualy causes the FK col update.

好的,我的错。我在global.asax的ApplicationStart中测试它,因此没有创建Request,因此会话没有被刷新。当我在一个简单的ConsoleApp项目上测试它时,我意识到它,当我看到刷新实际导致FK col更新时。

Anyway: thanks for help!

无论如何:谢谢你的帮助!

#2


In a "vanilla" parent-children object model, you must update the child's object's reference to the parent in order to cause NHibernate to update the child record's reference to the parent.

在“vanilla”父子对象模型中,必须更新子对象对父对象的引用,以使NHibernate更新子记录对父对象的引用。

In an "inverted" parent-children object model, you must modify the parent's collection of children objects in order to cause NHibernate to update the child records' references to the parent.

在“反向”父子对象模型中,必须修改父对象的子对象集合,以使NHibernate更新子记录对父对象的引用。

It seems you may want to be using an "inverted" parent-children object model.

看起来你可能想要使用“倒置”的父子对象模型。

In the XML mapping, you need

在XML映射中,您需要

<set name="Packets" cascade="all" inverse="true">
    <key column="OrderId" />
    <one-to-many class="Company.Product.Core.Packet, Core,
        Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</set>

In the Fluent mapping, you need

在Fluent映射中,您需要

HasMany<Packet>(x => x.Packets)
    .Cascade.All()
    .Inverse()
    .KeyColumnNames.Add("OrderId")
;

#3


This is really strange. You should check subsequent Updates, NHibernate sometimes updates foreign keys afterwards, and then it doesn't appear in the insert.

这真的很奇怪。您应该检查后续更新,NHibernate有时会更新外键,然后它不会出现在插入中。

Make sure that OrderId does not have several meanings on the Packets table. To check this, change the name of OrderId to something else.

确保OrderId在Packets表上没有多种含义。要检查此项,请将OrderId的名称更改为其他名称。

Cascading has nothing to do with it. It only controls if you need to save the child explicitly.

级联与它无关。它仅控制您是否需要明确保存子项。

#1


Ok, my fault. I was testing it in ApplicationStart of global.asax, so the Request hadn't been created so the session wasn't flushed. I realised it when I tested it on a simple ConsoleApp project when I saw that flushing actualy causes the FK col update.

好的,我的错。我在global.asax的ApplicationStart中测试它,因此没有创建Request,因此会话没有被刷新。当我在一个简单的ConsoleApp项目上测试它时,我意识到它,当我看到刷新实际导致FK col更新时。

Anyway: thanks for help!

无论如何:谢谢你的帮助!

#2


In a "vanilla" parent-children object model, you must update the child's object's reference to the parent in order to cause NHibernate to update the child record's reference to the parent.

在“vanilla”父子对象模型中,必须更新子对象对父对象的引用,以使NHibernate更新子记录对父对象的引用。

In an "inverted" parent-children object model, you must modify the parent's collection of children objects in order to cause NHibernate to update the child records' references to the parent.

在“反向”父子对象模型中,必须修改父对象的子对象集合,以使NHibernate更新子记录对父对象的引用。

It seems you may want to be using an "inverted" parent-children object model.

看起来你可能想要使用“倒置”的父子对象模型。

In the XML mapping, you need

在XML映射中,您需要

<set name="Packets" cascade="all" inverse="true">
    <key column="OrderId" />
    <one-to-many class="Company.Product.Core.Packet, Core,
        Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</set>

In the Fluent mapping, you need

在Fluent映射中,您需要

HasMany<Packet>(x => x.Packets)
    .Cascade.All()
    .Inverse()
    .KeyColumnNames.Add("OrderId")
;

#3


This is really strange. You should check subsequent Updates, NHibernate sometimes updates foreign keys afterwards, and then it doesn't appear in the insert.

这真的很奇怪。您应该检查后续更新,NHibernate有时会更新外键,然后它不会出现在插入中。

Make sure that OrderId does not have several meanings on the Packets table. To check this, change the name of OrderId to something else.

确保OrderId在Packets表上没有多种含义。要检查此项,请将OrderId的名称更改为其他名称。

Cascading has nothing to do with it. It only controls if you need to save the child explicitly.

级联与它无关。它仅控制您是否需要明确保存子项。