我有以下实体:
User
Role
然后是连接表:
UsersRoles (UserId, RoleId)
然后是RolePermissions表:
RolePermissions(Id, RoleId, ....)
所以在我希望能够做的用户实体上:
user.Roles
user.RolePermissions
我的UserMap看起来像:
public class UserMap : ClassMap<User>
{
public UserMap()
{
HasManyToMany(x => x.Roles)
.Table("RolesUsers")
.Access.CamelCaseField(Prefix.Underscore)
.ParentKeyColumn("UserId")
.ChildKeyColumn("RoleId")
.Cascade.All()
.Inverse();
}
}
现在我创建了一个新用户:
var user = new User { ... };
user.AddRole(new Role { .... } );
UserRepository.Create(user);
它会保存用户并保存角色,但不会插入到RolesUsers表中?
另外如何添加属性以获取用户的所有RolePermissions?
更新
我的角色地图有:
HasManyToMany(x => x.Users)
.Table("RolesUsers")
.Access.CamelCaseField(Prefix.Underscore)
.ParentKeyColumn("RoleId")
.ChildKeyColumn("UserId")
.Cascade.All();
我的单元测试确实通过了,但我认为这是因为我不知道如何清除第一级缓存,它甚至不会通过调用testUser
查询数据库:
[Test]
public void ShouldAddARoleToAUser()
{
int userId = -1;
using (var tx = UserRepository.SessionFactory.OpenSession().BeginTransaction())
{
var user = FactoryGirl.GetUser();
user.AddRole(FactoryGirl.GetRole());
UserRepository.Create(user);
tx.Commit();
UserRepository.SessionFactory.OpenSession().Flush();
userId = user.Id;
}
var testUser = UserRepository.Get(userId);
Assert.IsNotNull(testUser);
Assert.IsNotNull(testUser.Roles);
Assert.IsTrue(testUser.Roles.Count == 1);
Assert.IsTrue(testUser.Roles[0].Id > 0);
}
更新II
我的user.cs看起来像:
private IList<Role> _roles = new List<Role>();
public virtual IList<Role> Roles
{
get { return _roles; }
}
public virtual void AddRole(Role role)
{
if(!_roles.Contains(role))
{
_roles.Add(role);
}
}
Role.cs:
private IList<User> _users = new List<User>();
public virtual IList<User> Users
{
get { return _users; }
}
更新III
奇怪这是我的测试通过,但是看看探查器我可以看到它甚至没有命中sql server所以即使我调用Flush,然后做一个Get(userId)它正在加载实体从记忆里。 另外,查看关系(角色)的另一端,Role.Users是{}那么问题是什么?
答案 0 :(得分:2)
正如小伙子所说,.Inverse()
关于关系的声明是UserRole没有被持久化的原因。
取自Nhibernate的引用(这特别针对3.2,但对于NH的早期版本同样存在)http://nhibernate.info/doc/nh/en/index.html#collections-bidirectional 它明确地说:
“仅对关联的反向结束所做的更改不会保留”
然后更改关联的反向结束User.Roles
,当然,不会保留。
因此,您要么更改映射声明,要么更改代码以在关联的非反向端执行保存。如果您有其他代码依赖于User.Roles
ISession.Clear()
表示缓存上的压路器效果
ISession.Evict(entity)
,以及特定实体
答案 1 :(得分:1)
如果您正在为集合使用私人支持字段,我认为您必须像这样映射它们:
public class UserMap : ClassMap<User>
{
public UserMap()
{
HasManyToMany(x => x.Roles)
.Table("RolesUsers")
.Access.AsCamelCaseField(Prefix.Underscore)
.ParentKeyColumn("UserId")
.ChildKeyColumn("RoleId")
.Cascade.All()
.Inverse();
}
}
以上主要差异为.Access.AsCamelCaseField(Prefix.Underscore)
除此之外,我认为您需要将测试简化为以下内容:
User newUser = new User();
Role newRole = new Role();
newUser.AddRole(newRole);
newRole.AddUser(newUser);
using (NHibernate.ISession session = iSessionFactory.OpenSession())
{
using (NHibernate.ITransaction tran = session.BeginTransaction())
{
session.Save(newUser);
tran.Commit();
}
}
以上可能不准确,但我想你会明白我在说什么。
答案 2 :(得分:0)
验证您是否在事务中执行插入操作。如果没有它,NHibernate将不会在连接表中插入值