【问题标题】:Fluent NHibernate Parent-child cascade SaveOrUpdate failsFluent NHibernate 父子级联 SaveOrUpdate 失败
【发布时间】:2010-11-02 12:29:14
【问题描述】:

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

两个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 = new User() { Name = "test" }; Group g = new Group() { GroupName = "Test Group" }; u.Groups.Add(g);

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

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

【问题讨论】:

    标签: nhibernate fluent


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 这正是我作为解决方法所做的。不过我会认为这种类型的亲子关系相当普遍,因此会得到满足。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多