В настоящее время я работаю над проектом C#, в котором мы используем NHibernate. В проекте у нас есть таблица «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'
Разве они не должны вести себя одинаково?