NHibernate一行记录并执行两次查询

NHibernate一行记录并执行两次查询,nhibernate,fluent-nhibernate,Nhibernate,Fluent Nhibernate,我正在SQL Server Express 2008上使用:NHibernate、NHibernate.Linq和Fluent NHibernate。我正在使用引用属性上的谓词选择一个实体(多个映射)。我有fetch=join,unique=true,lazy-load=false。我启用了log4net日志,当任何这样的查询执行时,它都会记录两个相同的SQL查询。运行查询会返回一行,当我尝试使用IQueryable.Single扩展方法时,它会抛出异常,指出返回了多行。我还尝试使用标准IQue

我正在SQL Server Express 2008上使用:NHibernate、NHibernate.Linq和Fluent NHibernate。我正在使用引用属性上的谓词选择一个实体(多个映射)。我有fetch=join,unique=true,lazy-load=false。我启用了log4net日志,当任何这样的查询执行时,它都会记录两个相同的SQL查询。运行查询会返回一行,当我尝试使用IQueryable.Single扩展方法时,它会抛出异常,指出返回了多行。我还尝试使用标准IQuery.UniqueResult方法运行查询,结果相同,它最终记录日志并实际运行查询两次,然后抛出一个异常,指出有多行,但是在management studio中运行实际查询只返回一个结果。当我禁用日志记录时,我收到相同的错误

实体和映射声明如下(暗示适当的访问修饰符和成员类型差异)

类用户
{
int-ID;
字符串用户名;
}
类客户端
{
int-ID;
用户;
个人;
地址;
}
类UserMap:ClassMap
{
公共用户映射()
{
Id(x=>x.Id);
映射(x=>x.UserName);
}
}
类ClientMap:ClassMap
{
公共客户端映射()
{
Id(x=>x.Id);
引用(x=>x.User).Unique();
...
}
}
然后调用一个查询,如以下所示:

ISession s = GetNHibernateSession();

...

var client = s.Linq<Client>().SingleOrDefault(x => x.User.ID = 17);

or

var client = s.Linq<Client>().Where(x => x.User.ID = 17);

or

var client = s.CreateQuery("from Client as c where c.User.ID = 17").UniqueResult<Client>();
ISession s=GetNHibernateSession(); ... var client=s.Linq().SingleOrDefault(x=>x.User.ID=17); 或 var client=s.Linq(),其中(x=>x.User.ID=17); 或 var client=s.CreateQuery(“以c形式从客户端发送,其中c.User.ID=17”).UniqueResult(); 在所有情况下,执行两个相同的查询。当我启用延迟加载时,使用两个查询再次加载客户机,但是在访问成员(如Person)时,只执行一个额外的查询


这是否可能是Fluent生成不正确映射的结果?或者SQL Server Express edition没有被NHibernate正确使用?

NHibernate使用SQL Express没有任何问题,我已经广泛使用了它。类似地,在这个简单的场景中,Fluent NHibernate不太可能生成无效的映射(但并非闻所未闻)


这是瞎猜,但我相信NHibernate保留名称Id作为标识符名称,因此当它在查询中看到Id时,它知道只需查看外键,而不是实际连接的实体。也许您对ID而不是ID的命名会使它失效?

您可以尝试使用优秀的探查器来更详细地查看正在发生的事情。它有一个30天的试用许可证,在Beta版中,完全许可证成本有折扣

问题是由我声明的另一个映射引起的。我有一个从客户端继承的类,它有一个关联的映射。这就是导致NHibernate两次查询的原因。我注意到了这一点,因为在使用Linq()时,它返回的是子类,而不是客户机本身。这个继承和映射的特殊实例是我的一个设计缺陷,也是整个问题的根源

为什么不附加映射和实际查询代码呢。这样可以更容易地在代码中找到bug。
ISession s = GetNHibernateSession();

...

var client = s.Linq<Client>().SingleOrDefault(x => x.User.ID = 17);

or

var client = s.Linq<Client>().Where(x => x.User.ID = 17);

or

var client = s.CreateQuery("from Client as c where c.User.ID = 17").UniqueResult<Client>();