多对多关系在数据库也是比较常见的,它通过一个中间表将两个主表关联起来。
下面来看看多对多关联在nh的实现,示例是一个User和Group之间的多对多关联。
先来看看User类的映射信息:
在多对多定义中,定义了中间表为UserGroups,此表只有两个字段:user_id和group_id;用于关联Users和Groups表。
User的定义:
public class User
{
public User()
{
}
public int UserId
{
get { return userId; }
set { userId = value; }
}
public int Name
{
get { return name; }
set { name = value; }
}
public IDictionary Groups
{
get { return groups; }
set { groups = value; }
}
private int userId;
private string name;
private IDictionary groups = new Hashtable();
} //class User
这里用一个数据字典IDictionary对角来保存组对象。
再来看看Group类的映射信息:
这里many-to-many的定义和User类映射信息中的差不多。
组类的定义:
public class Group
{
public Group()
{
}
public int GroupId
{
get { return groupId; }
set { groupId = value; }
}
public int Name
{
get { return name; }
set { name = value; }
}
public int Description
{
get { return description; }
set { description = value; }
}
public IDictionary Users
{
get { return users; }
set { users = value; }
}
private int groupId;
private string name;
private IDictionary users = new Hashtable();
} //class Group
注意:多对多没有主次之分,保存时的两边都要save!
下面给出部分测试代码。
public void TestCreate()
{
User user1 = new User();
user1.Name = "test1";
User user2 = new User();
user2.Name = "test2";
Group group1 = new Group();
group1.Name = "group1";
Group group2 = new Group();
group2.Name = "group2";
user1.Groups.Add(group2, group2);
user2.Groups.Add(group1.group1);
group1.Users.Add(user2, user2);
group2.Users.Add(user1, user1);
ITransactioin trans = null;
try
{
trans = session.BeginTransaction();
Session.Save(user1);
Session.Save(user2);
Session.Save(group1);
Session.Save(group2);
trans.Commit();
}
catch (Exception e)
{
if (trans != null) trans.Rollback();
throw e;
}
finally
{
session.Close();
}
}
以上测试代码中session的相关操作请查看相关文档。
在实际应用中,我较少使用many-to-many映射,当然这要从性能和实际需要考虑。
我的做法是一个elements来取得所有关联的identity, 然后在需要的时候才加载对象,有点类似lazy, 但lazy有一个问题,就是session必须没有被释放,这在分层开发中较难办到。