У нас возникли проблемы с тем, как NHibernate (версия 4.0.0.4000 AND 4.0.4.4000 протестирована) возвращает duplicate. В приведенном ниже примере я получаю 566 результатов (правильный номер результатов), но только 549 являются уникальными, то есть имеется 17 дубликатов.NHibernate SetFirstResult приводит к дублирующим результатам
#region Get Record IDs
public IList<string> GetRecordIds(string user, string agency, DateTime utcFrom, DateTime utcTo, SearchDateRangeType dateRangeType, IEnumerable<string> status, IEnumerable<string> billingStatus, IEnumerable<string> qaStatus, IEnumerable<string> transmissionStatus, IEnumerable<string> scheduledTransmissions, int pageSize = -1, int pageNumber = -1)
{
using (ISession session = NHibernateHelper.OpenSession())
{
ICriteria crit = session.CreateCriteria<Metadata>();
var dateDisjunction = Restrictions.Disjunction();
dateDisjunction.Add(Restrictions.Between("IncidentDate", utcFrom, utcTo));
crit.Add(dateDisjunction);
if (string.IsNullOrEmpty(agency) == false)
{
crit.CreateAlias("Ownership._entities.AsIList", "entities");
crit.Add(Restrictions.Eq("entities._entityName._value", agency));
crit.Add(Restrictions.Eq("entities._isDeleted._value", false) || Restrictions.IsNull("entities._isDeleted._value"));
}
crit.AddOrder(Order.Asc(Projections.Property("RecordId")));
crit.SetProjection(Projections.Property("RecordId"));
if (pageSize > 0 && pageNumber > 0)
{
crit.SetFirstResult(pageSize * (pageNumber - 1)).SetMaxResults(pageSize);
}
var ret = crit.List<string>();
return ret;
}
}
#endregion
SQL Пример 1 является сгенерированным первого итерация кода из NHibernate. Последующие страницы (вторая страница вперед) используют ROW_NUMBER() OVER
. SQL Sample 2 - это созданная вручную первая страница, которая использует ROW_NUMBER() OVER
, как если бы это была следующая страница. NHibernate, по-видимому, «оптимизировал» прочь ROW_NUMBER() OVER
для первой страницы, и это кажется (?) Причиной нашей проблемы.
SQL Пример 1: Сгенерировано NHibernate. Вызывает дубликаты.
SELECT
TOP (100) this_.RecordId as y0_
FROM
PcrMetadata this_
inner join
PcrEntities entities1_
on this_.Id=entities1_.ListKey
WHERE
(
this_.IncidentDate between '0001-01-01 00:00:00.0000000' and '9999-01-01 00:00:00.0000000'
)
and entities1_.Name = 'ClientIDNumber'
and (
entities1_.Entities_IsDeleted = 0
or entities1_.Entities_IsDeleted is null
)
SQL Пример 2: Вручную создан на основе второй страницы NHibernate. Не вызывает дубликатов.
SELECT
TOP (100) this_.RecordId as y0_
FROM
(SELECT
this_.Record as y0_,
ROW_NUMBER() OVER(
ORDER BY
CURRENT_TIMESTAMP) as __hibernate_sort_row
FROM
PcrMetadata this_
inner join
PcrEntities entities1_
on this_.Id=entities1_.ListKey
WHERE
(
this_.IncidentDate between '0001-01-01 00:00:00.0000000' and '9999-01-01 00:00:00.0000000'
)
and entities1_.Name = 'ClientIDNumber'
and (
entities1_.Entities_IsDeleted = 0
or entities1_.Entities_IsDeleted is null
)) as query
WHERE
query.__hibernate_sort_row > 0 -- CHANGE THIS NUMBER
Я делаю что-то неправильно? Или что-нибудь, что я могу сделать, чтобы заставить NHibernate использовать ROW_NUMBER? Заранее благодарим за любую помощь!
Спасибо за ваш ответ! Просто я понимаю, есть ли проблема, даже если у Владения будет только одна запись, возвращенная из запроса? В обоих наборах сгенерированного SQL это конкретное имя, которое он ищет в Ownership, и в нашем приложении это будет одна строка. Я также проверил вручную SQL. – dythim
В случае, если есть ровно один (но вы должны быть уверены, что можете гарантировать, что даже с помощью некоторых подпрограмм DB), вы можете присоединиться к коллекции, и ваш пейджинг будет работать. Но мой опыт - НИКОГДА не делай этого. это по понятию неверно. Да, это зависит от вас, но ... по крайней мере, попытайтесь подумать о моих предложениях. Я показал вам, как создавать коллекции FITLER и даже SELECT без 1 + N ...в то же время могу быть в состоянии перечислить несколько элементов-списков –
Спасибо, я вижу, как то, что вы говорите, может быть проблемой, но я обеспокоен тем, что это не проблема, которую я вижу. Я вижу проблему с SQL, независимо от NHibernate. Два образца sql - это страница 0. NHibernate «оптимизировал» свою страницу 0 без 'ROW_NUMBER' - поэтому результат запроса должен быть таким же, как SQL-запрос с« ROW_NUMBER », но это не так. Имеет ли смысл моя логика? – dythim