我遇到了NHibernate的问题,正如我想的那样,懒惰负载。
我有两个相互关联的实体类:
public class User
{
// lots of properties
public virtual Role Role { get; set; }
}
public class Role
{
// properties
public virtual IList<User> UsersInRole { get;set; }
public Role()
{
this.UsersInRole = new List<User>();
}
}
关系是一对多(一个角色 - 许多用户)。 使用Fluent映射类如下:
public class UserMapping : ClassMap<Models.Accounts.User>
{
public UserMapping()
{
this.Table("Users");
this.Id(u => u.ID).GeneratedBy.Native();
//properties mapping
this.References<Models.Accounts.Role>(u => u.Role);
}
}
public class RoleMapping : ClassMap<Models.Accounts.Role>
{
public RoleMapping()
{
this.Table("Roles");
this.Id(r => r.ID).GeneratedBy.Native();
// properties mapping
this.HasMany<User>(r => r.Users).AsBag().Inverse().KeyColumn("Role_id");
}
}
当我创建一个角色并为其分配一些用户时,Role :: Users属性为null,直到会话关闭并打开另一个。因此,请考虑以下代码:
object Foo()
{
var session = FluentManager.OpenNewSession();
var t1 = session.BeginTransaction();
Role role = new Role("admin");
session.SaveOrUpdate(role);
t1.Commit();
var t2 = session.BeginTransaction();
session.SaveOrUpdate(new User() { Login = "log1", Role = role });
t2.Commit();
Role oldRole = session.Get<Role>((uint)1);
return oldRole.Users; // null here
}
另一方面,以下代码可以正常工作:
object Foo()
{
var session = FluentManager.OpenNewSession();
var t1 = session.BeginTransaction();
Role role = new Role("admin");
session.SaveOrUpdate(role);
t1.Commit();
var t2 = session.BeginTransaction();
session.SaveOrUpdate(new User() { Login = "log1", Role = role });
t2.Commit();
session.Close();
var session2 = FluentManager.OpenNewSession();
Role oldRole = session2.Get<Role>((uint)1);
return oldRole.Users; // Actual list of users
}
尽管如此,我想在一个给定的角色中处理用户集合。我做错了什么? 非常感谢提前。
PS:如果重要的话,我正在使用Fluent NHibernate 1.2和SQLite数据库。
答案 0 :(得分:2)
第一个示例中role.Users为null的原因是因为您没有手动处理此关系。您需要自己维护双向关系。在您的第一个示例中,它没有从数据库中获取您的Role对象。它是从Session获得的。在您的第二个示例中,您关闭会话并打开一个新会话。这会强制它从数据库中读取信息,此时您的关系将保持不变。以下是我可以采取的措施来纠正这个问题:
public class User
{
// lots of properties
public virtual Role Role { get; set; }
}
public class Role
{
// properties
public virtual IList<User> UsersInRole { get;set; }
public Role()
{
this.UsersInRole = new List<User>();
}
public void AddUser(User user)
{
if(UsersInRole.Contains(user))
return;
user.Role = this;
UsersInRole.Add(user);
}
}
您的示例现在看起来像这样:
object Foo()
{
var session = FluentManager.OpenNewSession();
var t1 = session.BeginTransaction();
Role role = new Role("admin");
session.SaveOrUpdate(role);
t1.Commit();
var t2 = session.BeginTransaction();
User newUser = new User();
newUser.Login = "log1";
//This takes care of our relationships
role.AddUser(newUser);
session.SaveOrUpdate(newUser);
t2.Commit();
Role oldRole = session.Get<Role>((uint)1);
return oldRole.Users; // This should be fine here since we used AddUser
}
您还可以查看以下内容以获取更多详细信息:
Getting ManyToMany relationship to load
答案 1 :(得分:0)
黑暗中的一些镜头:
您是否尝试过访问role.Users
而不是oldRole.Users
?
您是否尝试删除Role的构造函数?
您是否尝试使用分离的条件或QueryOver
而不是Get
来获取角色?也许你的角色错了。