nHibernate因whereNot限制而失败,但因where限制而失败

时间:2020-04-21 07:36:45

标签: c# sql-server nhibernate nhibernate-mapping

我目前正在使用NHibernate的C#项目中工作。 在项目中,我们有一个名为“ Auftrag”的表,我只需要一些列即可。

仅选择我需要的列,我使用以下代码:

ProjectionList projectionListSubTypeAuftrag = Projections.ProjectionList();
projectionListSubTypeAuftrag
    .Add(Projections.Property("AuftragID"), "Id")
    .Add(Projections.Property("Status"), "Status")
    .Add(Projections.Property("Typ"), "Typ");

DetachedCriteria auftragCriteria = DetachedCriteria.For(typeof(Auftrag));

auftragCriteria.SetProjection(projectionListSubTypeAuftrag);
auftragCriteria.SetResultTransformer(Transformers.AliasToBean(typeof(SubTypeAuftrag)));

IList<SubTypeAuftrag> auftragSubview;

using (ITransaction tx = session.BeginTransaction())
{
    auftragSubview = auftragCriteria.GetExecutableCriteria(session).List<SubTypeAuftrag>();

    tx.Commit();
}

这可以正常工作并返回表中的所有行。现在,我要使用条件Status != 'A'进行过滤。

我尝试通过以下代码实现这一目标

auftragCriteria.Add(Restrictions.Not(Restrictions.Eq("Status", 'A')));

如果我现在运行代码,则会出现异常:

System.Data.SqlClient.SqlException:创建或更改表 “ FakeWorkTable”失败,因为最小行大小为16017, 包括4个字节的内部开销。这超过了最大值 表格的允许行大小为8094字节。

当我查看生成的SQL语句时,一切看起来都很正常,我也可以在Microsoft SSMS中运行它。

现在我不了解的部分是,当我将auftragCriteria.Add(Restrictions.Not(Restrictions.Eq("Status", 'A')));更改为auftragCriteria.Add(Restrictions.Eq("Status", 'A'));时,一切正常。

我想念什么?

我找到了一种解决方法:

auftragCriteria.Add(Expression.Sql("Status <> 'A'"));

有效。

如果我使用auftragCriteria.Add(Restrictions.Not(Restrictions.Eq("Status", 'A')));,则会收到此SQL查询

SELECT this_.auftragid as y0_,
       this_.status    as y1_,
       this_.typ       as y2_
FROM   auftrag this_
WHERE  not (this_.status = 'A' /* @p0 */)

如果我使用auftragCriteria.Add(Expression.Sql("Status <> 'A'"));,我会得到:

SELECT this_.auftragid as y0_,
       this_.status    as y1_,
       this_.typ       as y2_
FROM   auftrag this_
WHERE  Status <> 'A'

他们的行为不一样吗?

1 个答案:

答案 0 :(得分:0)

就我从查看NHibernate源代码的角度来看,使用Restrictions.Not(Restrictions.Eq("Status", 'A'))似乎是实现“不等于”运算符的正确方法。在Java版本的Hibernate中,有Restrictions.ne被转换为'<>'运算符。

我要检查的几件事。使用最新的NHibernate版本运行代码,然后查看问题是否仍然存在。从错误消息来看,我怀疑您在此处显示的代码中还有更多的事情发生。尝试用尽可能少的代码来复制问题。

我认为比使用Expression.Sql更好的另一种解决方法是将LtGtOr一起使用:

auftragCriteria.Add(
    Restrictions.Or(
        Restrictions.Lt("Status", 'A'), 
        Restrictions.Gt("Status", 'A')));

应该成为:

WHERE (this_.status < 'A' or this.status > 'A')

PS:我写了一个使用NHibernate 5.1.6和Restrictions的小例子。我认为您的问题与NHibernate版本无关。

相关问题