2010-11-02 57 views
2

我有一个父子关系,我已经把测试用例放在用户和用户组之间。我这样做是为了在尝试使用关系执行cacade插入时复制父亲 - 子女关系中的故障 。流利NHibernate父子级联SaveOrUpdate失败

两个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 =新用户(){姓名=“测试”}; Group g = new Group(){GroupName =“Test Group”}; u.Groups.Add(g);

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

但是它失败,出现异常“无法将NULL值插入列‘用户ID’,表‘test.dbo.Group’;列不允许空INSERT失败 的语句已终止。”。我怀疑这是dude父对象的Id(一个标识列)作为NULL传递,而不是新的值。这是一个错误还是有办法解决这些映射,以便这个级联关系成功?

回答

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) 


} 

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

+1

这正是我所做的解决方法。不过,我会认为这种亲子关系是相当普遍的,因此会得到照顾。 – Dion 2010-11-02 19:48:43

4

我最近有这种确切类型的映射在一个项目中工作正常。我的建议是:

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

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

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

+0

+1,因为反向是IMO的方式 – Firo 2012-03-01 16:54:26