与NHIbernate的多对多关系的XML映射文件

时间:2011-03-21 14:31:13

标签: c# linq nhibernate nhibernate-mapping linq-to-nhibernate

我有一个用户表,字段:Id,用户名

我有一个表UserGroup,字段:Id,UsergroupName,Code

我想按用户分配几个Usergroup,这意味着,我必须有第三个表:UserId和UsergroupId,这些表名为UsersGroups

我试过这段代码:

用户表,XML:

<bag name="UsersGroups" generic="true" cascade="all" inverse="false" table="UsersGroups" >
    <key column="UserId" />
    <many-to-many column="GroupId" class="LookupUserGroup" />
</bag>

用户表,C#:

public virtual IList<UserGroup> UsersGroups { get; set; }

组表,C#(XML映射中没有任何内容):

public virtual User User { get; set; }

要向用户添加组,我在User类中使用AddGroup,我这样做:

public virtual void AddGroup(UserGroup userGroup)
{
    userGroup.User = this;
    UsersGroups.Add(userGroup); 
}

当我对用户进行查询时,我想使用linq对“代码”字段进行一些检查,如下所示:

var res = (from c in MyUserList where c.UserGroup.Code == 1 select c);但在智能感知中无法使用USergroup字段。

有什么想法吗?

谢谢,

2 个答案:

答案 0 :(得分:2)

首先,您的C#类的设计似乎是错误的。它们并不反映你有多对多关系的意图,而是一对多的关系。由于每组只允许一个用户通常没有意义,因此您应该将UserGroup类更改为

public class UserGroup
{
    [...]

    public virtual IList<User> Users { get; set; }
}

并更改映射:

<bag name="Users" table="UsersGroups" lazy="true" cascade="all" inverse="true" >
    <key column="GroupId"></key>
    <many-to-many column="UserId" class="User" />
</bag>

LookupUserGroup班级是否正确?在这种多对多关系的简单情况下,您应该只有三个表的两个类。如果您有User类和UserGroup类,请删除LookupUserGroup类并将其替换为User.hbm.xml中的映射。

User类中的AddGroup方法看起来有点像这样:

public virtual void AddGroup(UserGroup userGroup)
{
    if(!this.UsersGroups.Contains(userGroup))
    {
         this.UsersGroups.Add(userGroup);
         userGroup.Users.Add(this); 
    }
}

intellisense不提供UserGroup字段的原因只是您没有这样的字段。该字段称为UsersGroups(应该是UserGroups),并且是IList<UserGroup>

不幸的是,NHibernate 3.0中当前的Linq提供程序并不真正支持您尝试在此处执行的查询。相反,您可以尝试使用QueryOver。在你的情况下,它看起来像这样(改编自NHibernate QueryOver with ManytoMany

var result = Session.QueryOver<User>()
    .Right.JoinQueryOver<UserGroup>(x => x.UserGroups) // the .Right. might not be required
    .Where(c => c.Code == 1)
    .List();

我没有实施或测试任何此类内容,因此可能会出现轻微错误。

答案 1 :(得分:1)

Kris,关于你的设计决定的简短说明。如果您真的想拥有真正的多对多关系,那么您不需要第三个实体(UserGroup)。您只需要用户和组实体。 Nhibernate将自己处理中间表的创建。但是,我从不使用这种方法。您采用的方法(使用用户组实体)是我更喜欢的方法,因为它为您提供了额外的灵活性。你永远不知道什么时候需要在用户和组之间的关系中有额外的信息(用户被添加到组的日期,谁创建了这种关系等等)所以我会使用UsersGroups实体,但是创建关系的方式是用户组和用户组之间的多对一关系,以及组和用户组之间的多对一关系。通过这种方式,您可以获得额外的灵活性。