User
有很多Role
s:
public class User
{
private ISet<Role> _roles = new HashSet<Role>();
public virtual ISet<Role> Roles { get { return _roles; } }
}
我向用户添加角色(user1.Roles.Add(role1)
)。
为什么这两个查询中的第一个不会将user1
作为第二个返回?
session.QueryOver<User>()
.JoinQueryOver<Role>(u => u.Roles)
.Where(x => x.Id == role1.Id)
.List();
session.QueryOver<User>().List()
.Where(u => u.Roles.Contains(role1));
答案 0 :(得分:0)
此魔法行为的答案隐藏在Session
模式及其.Flush()
操作中。
ISession(见Chapter 2. Architecture):
ISession(NHibernate.ISession)
单线程,短期对象,表示应用程序与持久性存储之间的对话。包装ADO.NET连接。 ITransaction的工厂。 保存持久对象的强制(第一级)缓存,在导航对象图或按标识符查找对象时使用。
这里有趣的是first-level
缓存... identifier
。发生的事情是User
内部更新了ISession
。仅在此会话中,因为它未与DB同步...它没有刷新
9.6. Flush是(简而言之) NHibernate的方式
ISession会不时执行同步 ADO.NET连接状态所需的SQL语句内存中保存的对象状态。此过程刷新默认情况下发生在以下几点......(请参阅链接中的更多内容)
所以,我们现在知道的是:会话正在保持用户的更新记录。 DB没有,因为没有调用session.Flush()。我们运行第二个查询,如下所示:
session.QueryOver<User>()
// forces to load all rows from DB
// these rows are converted into User instances by their ID
// and while our updated User in memory already is... it will be used
// instead of persisted one
.List()
// now we do in memory searching
// i.e. check the User instances, which of them does have role1
// and even our newly updated (just in memory) user is found
.Where(u => u.Roles.Contains(role1));
第二个查询,确实在数据库端进行过滤...但未完成同步...没有.Flush()
...找不到用户。
所以,请阅读上面提到的内容,以便更详细地了解:会话,一级缓存和刷新
打电话:
session.Flush() // after adding Role1 to User
在向用户添加角色时立即...并且两个查询都将返回相同的结果