流畅的NHibernate父子级联SaveOrUpdate失败

时间:2010-11-02 12:29:15

标签: nhibernate fluent

我有一个亲子关系,我在用户和组之间放了一个测试用例。我这样做是为了复制失败 尝试使用thes关系执行cacade插入时的父子关系。

两个SQL表如下:

CREATE TABLE [dbo].[User]
(
    [Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [Name] [varchar](50) NOT NULL,
)
CREATE TABLE [dbo].[Group]
(
    [Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [GroupName] [varchar](50) NOT NULL,
    [UserId] [int] NOT NULL,
)

ALTER TABLE [dbo].[Group]  WITH CHECK ADD  CONSTRAINT [FK_Group_User] FOREIGN KEY([UserId])
REFERENCES [dbo].[User] ([Id])

对象用以下映射表示这两个表:

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Table("[User]");
        Id(x => x.Id).GeneratedBy.Identity();
        Map(x => x.Name).Not.Nullable();
        HasMany(x => x.Groups).KeyColumn("UserId").Cascade.SaveUpdate();
    }
}

public class GroupMap : ClassMap<Group>
{
    public GroupMap()
    {
        Table("[Group]");
        Id(x => x.Id).GeneratedBy.Identity();
        Map(x => x.GroupName).Not.Nullable();
        References(x => x.User).Column("UserId").Not.Nullable();
    }
}

创建对象的代码很简单:

用户u =新用户(){Name =“test”};         组g = new Group(){GroupName =“Test Group”};         u.Groups.Add(克);

    using (var session = factory.OpenSession())
    {
        session.SaveOrUpdate(u);
    }

然而它失败,异常“无法将值NULL插入列'UserId',表'test.dbo.Group';列不允许空值.INSERT失败。 该语句已被终止“。我怀疑这是父对象的Id(一个标识列)被传递为NULL而不是新值。这是一个错误还是有办法修复这些映射,以便这个级联关系成功了?

2 个答案:

答案 0 :(得分:4)

我最近在项目中使用了这种确切类型的映射。我的建议是:

  • 了解HasMany关系的Inverse属性如何工作。 Great explanation here
  • 您需要父对象和子对象之间的双向关联。这可以在上面链接的文章的底部解释。

另一个好建议是更好地封装您的馆藏 - 不要直接访问集合修改方法。集合属性应该是只读的,父节点(在您的情况下为User类)应该具有更改私有集合的AddGroup()和RemoveGroup()方法。为了使其工作,您必须让NHibernate通过使用.Access.CamelCaseField(Prefix.Underscore)或类似的映射属性来访问私有集合成员。 Good discussion about it here

如果需要,我可以发布示例映射和类文件。

答案 1 :(得分:3)

您必须先保存用户,然后将该组分配给用户并保存:

using (var session = factory.OpenSession())
    {

User u = new User() { Name = "test"};
    session.SaveOrUpdate(u);

Group g = new Group() { GroupName = "Test Group", User = u };
session.SaveOrUpdate(g)


}

我发现你不能级联保存刚刚创建的子/父相关对象。