刚学习Nhibernate遇到了这个问题
用常用的用户和角色来描述many to many的问题:
下面是映射文件(使用FluentNHibernate生成后去掉了省略掉部分):
<class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="User">
.......
<bag cascade="all" lazy="true" name="Roles" table="S_UserInRole" mutable="true">
<key>
<column name="UID" />
</key>
<many-to-many class="Role">
<column name="RID" />
</many-to-many>
</bag>
</class>
<class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="Role">
.......
<bag cascade="all" lazy="true" name="Users" table="S_UserInRole" mutable="true" inverse="true">
<key>
<column name="RID" />
</key>
<many-to-many class="User">
<column name="UID" />
</many-to-many>
</bag>
</class>
public void AddUserToRole(string userID, string roleID)
{
using (ISession _session = SessionFactory.Get().OpenSession())
{
using (ITransaction tran = _session.BeginTransaction())
{
try
{
MSRole role = _session.Get<MSRole>(roleID);
MSUser u = role.Users.FirstOrDefault(o => o.ID == userID);
if (null == u)
{
MSUser entity = _session.Load<MSUser>(userID);
//entity.ID = userID;
//entity.Roles = new List<MSRole>();
role.Users.Add(entity);
entity.Roles.Add(role);
_session.Update(entity); //_session.Update(role);
_session.Flush();
}
tran.Commit();
}
catch (HibernateException)
{
tran.Rollback();
throw;
}
}
}
}AddUserToRole("35a74933-e881-4f85-bf95-24592d7e6796","1128");用Nunit测试 得到Nhibernate产生的sql语句:NHibernate: INSERT INTO S_UserInRole (UID, RID) VALUES (@p0, @p1);@p0 = '35a74933-e881-4f85-bf95-24592d7e6796', @p1 = '1128'NHibernate: DELETE FROM S_UserInRole WHERE UID = @p0;@p0 = '35a74933-e881-4f85-bf95-24592d7e6796'NHibernate: INSERT INTO S_UserInRole (UID, RID) VALUES (@p0, @p1);@p0 = '35a74933-e881-4f85-bf95-24592d7e6796', @p1 = 'f089cee5-9cac-4301-b988-d224619ca263'(上面Insert为S_UserInRole表原有的一条记录)NHibernate: INSERT INTO S_UserInRole (UID, RID) VALUES (@p0, @p1);@p0 = '35a74933-e881-4f85-bf95-24592d7e6796', @p1 = '1128'//预想的是只需要最后一条SQL语句,而Nhibernate却是先删除所有再insert
public void RemoveUserFromRole(string userID, string roleID)
{
using (ISession _session = SessionFactory.Get().OpenSession())
{
using (ITransaction tran = _session.BeginTransaction())
{
try
{
MSRole entity = _session.Get<MSRole>(roleID);
if (null != entity)
{
MSUser user = entity.Users.FirstOrDefault(o => o.ID == userID);
if (user != null)
{
entity.Users.Remove(user);
user.Roles.Remove(entity);
_session.Update(user);//_session.Update(entity);
_session.Flush();
tran.Commit();
}
}
}
catch (HibernateException)
{
tran.Rollback();
throw;
}
}
}
}RemoveUserFromRole("35a74933-e881-4f85-bf95-24592d7e6796","1128");测试 Nhibernate生成的sql语句为:NHibernate: DELETE FROM S_UserInRole WHERE UID = @p0;@p0 = '35a74933-e881-4f85-bf95-24592d7e6796' NHibernate: INSERT INTO S_UserInRole (UID, RID) VALUES (@p0, @p1);@p0 = '35a74933-e881-4f85-bf95-24592d7e6796', @p1 = 'f089cee5-9cac-4301-b988-d224619ca263'// 预想 SQL:DELETE FROM S_UserInRole WHERE UID = @p0 and RID=@p1;@p0 = '35a74933-e881-4f85-bf95-24592d7e6796',@p1='1128'//
按上面我的写法,Nhibernate会先把中间表中所有关联记录删除掉再重新insert,每添加一次对应关系,都会先删除所有对应关系再重新insert就太不合理了。
上面的映射文件和代码该如何修改