流利-NHibernate的多对许多级联不填充链路表 [英] Fluent-NHibernate many-to-many cascade does not populate the link table

查看:145
本文介绍了流利-NHibernate的多对许多级联不填充链路表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

确定,不管我如何定义这些映射,我的很多一对多映射不希望与级联插入工作。我尝试了各种组合的级联()反向()键,删除所有不必要的属性只是为了了解他们是否有任何与此不工作,但没有锁。

这是非常简单的东西:我有一个消息(如电子邮件),这是从用户发送(我称之为实体 BasicUser )到多个用户(通过属性)。 用户消息在收件人而言有许多一对多的关系,但 FROMUSER 有一个一对多。 FROMUSER工作正常,并更新好了,但我的问题是许多一对多。我甚至删除 FROMUSER 和关系,只是为了检查,如果这是问题,但并没有帮助。

因此​​,这里的表设计(已移除 FROMUSER BasicUser 的关系,为简单起见)

和这里的映射:

 公共类MessageMap:ClassMap<消息>
{

    公共MessageMap()
    {
        ID(X => x.Id).COLUMN(的MessageId);
        地图(X => x.Subject);
        地图(X => x.SentAt);
        地图(X => x.Body);
        参考文献(X => x.From).COLUMN(FROMUSER);
        HasManyToMany(X => x.To)。。表(BasicUserMessage)ChildKeyColumn(BasicUserId)
            .ParentKeyColumn(的MessageId)级联()所有()。
    }
}

公共类BasicUserMap:ClassMap< BasicUser>
{
    公共BasicUserMap()
    {
        ID(X => x.Id).COLUMN(BasicUserId);
        地图(X => x.DisplayName);
        地图(X => x.Username);
        HasManyToMany(X => x.Messages)。。表(BasicUserMessage)ChildKeyColumn(的MessageId)
            .ParentKeyColumn(BasicUserId)反()。
    }
}
 

我呼吁这一点,这是行不通的(表 BasicUserMessage 没有得到填充): (注意:用户ID为1,2和3是存在的 - 我还试图从数据库中获取它们,然后添加到列表仍然没有工作)

  ISessionFactory厂=了getSessionFactory();
ISession的会话= factory.OpenSession();
消息m =新信息()
                {
                    身体=请注意2,
                    主题=秘密2,
                    从=新BasicUser(){ID = 2},
                    SentAt = DateTime.Now,
                };
m.To.Add(新BasicUser(){ID = 1});
m.To.Add(新BasicUser(){ID = 3});
session.SaveOrUpdate(米);
session.Close();
 

解决方案

有关事务的答案是正确的逐偶然一遇。也是正确的逐偶然发生的,这是因为你正在使用类似的身份发电机,需要一个数据库旅途上保存,以获得身份而表现出来的这种。

下面是当你设定的NHibernate做什么保存更新级联(或这意味着任何级联)在这样一个多一对多关联:

保存父实体。这一切都因为身份的策略立即数据库。该集合修改(因为它是新的),所以让我们来看看它的成员。这一步仅上没有关系的父母的映射设置发生。在创建为他们每个人的链接表中的条目。

别急,有些内容都是短暂的。瀑布设置是否正确,所以这是好的 - 但为了创建会话连接表项,我们需要这些儿童的ID,所以让我们马上将其保存

现在所有相关实体是持久的,而会话具有的待插入的所有的链接表中的条目。冲洗会议将发出的命令,并创建的条目。

当你包在一个事务中的code,提交事务刷新了会议,所以,当你提交创建。如果您使用不需要DB往返的标识生成器,然后链接表项和实体都插在同一时间,所以你不会看到断开,你所看到的 - 如果该会议是从来没有刷新,不会将任何东西插入,并且当它被刷新,一切都被插入。如果你有没有这些东西,明确冲洗你的会议将创建链接表项,一切都会好起来。

OK, no matter how I define these mappings, my many-to-many mapping does not want to work with cascade insert. I have tried various combination of Cascade() with Reverse() and removing all unnecessary properties just to understand if they had anything to do with this not working, but no lock.

It is really Simple stuff: I have a Message (like an email) which is sent from a user (I have called the entity BasicUser) to a number of users (through property To). User and Message in terms of recipients have a many-to-many relationship but FromUser has one-to-many. FromUser works fine and it is updated alright but my problem is with many-to-many. I even removed FromUser and relationship just to check if this was the problem, but did not help.

So here is the table design (Have removed the relationship from FromUser to BasicUser for simplicity)

And here are the mappings:

public class MessageMap : ClassMap<Message>
{

    public MessageMap()
    {
        Id(x => x.Id).Column("MessageId");
        Map(x => x.Subject);
        Map(x => x.SentAt);
        Map(x => x.Body);
        References(x => x.From).Column("FromUser");
        HasManyToMany(x => x.To).Table("BasicUserMessage").ChildKeyColumn("BasicUserId")
            .ParentKeyColumn("MessageId").Cascade().All();
    }
}

public class BasicUserMap : ClassMap<BasicUser>
{
    public BasicUserMap()
    {
        Id(x => x.Id).Column("BasicUserId");
        Map(x => x.DisplayName);
        Map(x => x.Username);
        HasManyToMany(x => x.Messages).Table("BasicUserMessage").ChildKeyColumn("MessageId")
            .ParentKeyColumn("BasicUserId").Inverse();
    }
}

And I call this and it does not work (table BasicUserMessage does not get populated): (Note Users with Id 1, 2 and 3 do exist - I also tried getting them from database and then add to list still did not work)

ISessionFactory factory = GetSessionFactory();
ISession session = factory.OpenSession();
Message m = new Message()
                {
                    Body = "Please note 2",
                    Subject = "Secret 2",
                    From = new BasicUser(){Id = 2},
                    SentAt = DateTime.Now,
                };
m.To.Add(new BasicUser(){Id = 1});
m.To.Add(new BasicUser(){Id=3});
session.SaveOrUpdate(m);
session.Close();

解决方案

The answer about transactions is correct-by-incidental-occurrence. Also correct-by-incidental occurrence is that this is manifesting itself as such because you are using something like an IDENTITY generator that requires a database trip on save to obtain the identity.

Here is what NHibernate does when you set a save-update cascade (or any cascade which implies that) on a many-to-many association with such:

Save the parent entity. This goes to the database immediately because of the identity strategy. The collection is "modified" (because it's new), so let's look at it's members. This step only occurs if inverse is not set on the parent's mapping of the relationship. Create an entry in the link table for each of them.

But wait, some of these entries are transient. Cascades are set properly, so that's okay - but in order to create the link table entry in the session, we need the id of those children, so let's save them immediately.

Now all relevant entities are persistent, and the session has a pending insert for all of the entries in the link table. Flushing the session will issue the commands and create those entries.

When you wrap your code in a transaction, committing the transaction flushes the session, so that is created when you commit. If you use an identity generator that doesn't require a DB round-trip, then the link table entries and the entities are all inserted at the same time, so you won't see the "disconnect" that you're seeing - if the session is never flushed, nothing is ever inserted, and when it is flushed, everything is inserted. If you have neither of these things, flushing your session explicitly will create the link table entries and all will be well.

这篇关于流利-NHibernate的多对许多级联不填充链路表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆