Я пытаюсь получить старый запрос, переведенный в Nhibernate. Мы обновляем старый проект от Nhibernate 2 до последней версии. Я использую синтаксис QueryOver, поскольку Linq не был вариантом из-за сложности запросов (советы коллеги).Nhibernate Group By and Alias To Bean
Я хочу запросить DB (Oracle), чтобы получить некоторые результаты, которые необходимо сгруппировать. В результате мне нужна сгруппированная коллекция моего DTO. Я также заметил, что nhibernate имеет проблемы с переводом на DTO со сложными свойствами (вложенными DTO) Чтобы исправить это, я нашел this тему. Это отлично работает, но я не поклонник магических струн ...
Я добавлю некоторые фрагменты кода о том, как мой вопрос с монстром смотрит на этот момент. Проблема в том, что я не могу понять, как добавить группу, не нарушая все остальное. Поэтому я хотел бы группировать объекты, но по-прежнему имею DTO в своих результатах. Что-то вроде:
ILookup<int,IEnumerable<NieuwePrintopdrachtenInfo>>
Любая помощь будет радушна.
К сожалению переменные и классы в голландском -_-
SYNUITGAANDEBRIEF uitgaandebrief = null;
SYNAANVRAAG joinedAanvraag = null;
SYNDOSSIER joinedDossier = null;
SYNVERBRUIKSADRES joinedVerbruiksAdres = null;
SYNEAN joinedEan = null;
SYNCTENERGIETYPE joinedEnergieType = null;
SYNBRIEFBESTEMMELINGEN joinedBriefBestemmeling = null;
SYNCTBRIEFTYPE joinedBriefType = null;
SYNCTBRIEFSTATUS joinedBriefStatus = null;
SYNCONTACTPERSOON joinedContactpersoon = null;
SYNCTCONTACTPERSOONTYPE joinedBestemmelingType = null;
SYNCTVERZENDMODUSTYPE joinedVerzendModus = null;
SYNCTCONTACTPERSOONTYPE joinedContactpersoonType = null;
SYNCTTAAL joinedContactpersoonTaal = null;
SYNTOEWIJZVERBRUIKVERANT joinedVerbruiksVerantw = null;
SYNCTPROFIELGROEP joinedProfielGroep = null;
var baseQuery = SessionHandler.CurrentSession.QueryOver(() => uitgaandebrief)
.JoinAlias(() => uitgaandebrief.AANVRAAGCollection,() => joinedAanvraag)
.JoinAlias(() => joinedAanvraag.DOSSIER,() => joinedDossier)
.JoinAlias(() => joinedDossier.VERBRUIKSADRES,() => joinedVerbruiksAdres)
.JoinAlias(() => joinedAanvraag.EAN,() => joinedEan)
.JoinAlias(() => joinedEan.CtEnergietype,() => joinedEnergieType)
.JoinAlias(() => uitgaandebrief.BRIEFBESTEMMELINGENCollection,() => joinedBriefBestemmeling)
.JoinAlias(() => uitgaandebrief.CtBriefType,() => joinedBriefType)
.JoinAlias(() => uitgaandebrief.CtBriefStatus,() => joinedBriefStatus)
.JoinAlias(() => joinedBriefBestemmeling.CONTACTPERSOONCollection,() => joinedContactpersoon, JoinType.LeftOuterJoin)
.JoinAlias(() => joinedBriefBestemmeling.CtContactPersoonType,() => joinedBestemmelingType, JoinType.LeftOuterJoin)
.JoinAlias(() => joinedBriefBestemmeling.CtVerzendModus,() => joinedVerzendModus, JoinType.LeftOuterJoin)
.JoinAlias(() => joinedContactpersoon.CtContactpersoonType,() => joinedContactpersoonType, JoinType.LeftOuterJoin)
.JoinAlias(() => joinedContactpersoon.CtTaal,() => joinedContactpersoonTaal, JoinType.LeftOuterJoin)
.JoinAlias(() => joinedContactpersoon.TOEWIJZVERBRUIKVERANTCollection,() => joinedVerbruiksVerantw, JoinType.LeftOuterJoin)
.JoinAlias(() => joinedContactpersoon.CtProfielGroep,() => joinedProfielGroep, JoinType.LeftOuterJoin);
Это только начало. Здесь идет часть фильтрации результатов (при необходимости).
if (briefType.HasValue)
{
baseQuery.Where(() => uitgaandebrief.BriefType == briefType.Value);
}
if (verzendModus.HasValue)
{
baseQuery.Where(() => joinedBriefBestemmeling.VerzendModus == verzendModus.Value);
}
if (!string.IsNullOrEmpty(binnenland) && binnenland.Trim() != "-1")
{
baseQuery.Where(() => joinedBriefBestemmeling.BinnenLand == binnenland.ToBoolean());
}
Тогда я получил роль, чтобы выбрать материал, который мне нужно, и перевести его в DTO (NieuwePrintopdrachtenInfo).
NieuwePrintopdrachtenInfo nieuwePrintopdrachtInfo = null;
baseQuery.SelectList(list => list
.Select(() => uitgaandebrief.UitgaandebriefId).WithAlias(() => nieuwePrintopdrachtInfo.UitgaandeBriefId)
.Select(() => uitgaandebrief.DatumInplanning).WithAlias(() => nieuwePrintopdrachtInfo.InplanningsDatum)
.Select(() => uitgaandebrief.ErrorReden).WithAlias(() => nieuwePrintopdrachtInfo.Probleem)
.Select(() => uitgaandebrief.ErrorNr).WithAlias(() => nieuwePrintopdrachtInfo.ErrorNummer)
.Select(() => uitgaandebrief.DatumCreatie).WithAlias(() => nieuwePrintopdrachtInfo.CreatieDatumBrief)
.Select(() => uitgaandebrief.DatumUpdate).WithAlias(() => nieuwePrintopdrachtInfo.DatumLaatsteWijzigingBrief)
.Select(() => uitgaandebrief.UserCreatie).WithAlias(() => nieuwePrintopdrachtInfo.BrieUserCreatie)
.Select(() => uitgaandebrief.UserUpdate).WithAlias(() => nieuwePrintopdrachtInfo.BriefUserUpdate)
.Select(() => uitgaandebrief.DatumAnnulatieElektriciteit).WithAlias(() => nieuwePrintopdrachtInfo.DatumElektriciteitGeannuleerd)
.Select(() => uitgaandebrief.DatumAnnulatieGas).WithAlias(() => nieuwePrintopdrachtInfo.DatumGasGeannuleerd)
.Select(() => joinedDossier.DossierId).WithAlias(() => nieuwePrintopdrachtInfo.DossierId)
.Select(() => joinedDossier.DossierNr).WithAlias(() => nieuwePrintopdrachtInfo.DossierNr)
.Select(() => joinedEnergieType.Omschrijving).WithAlias(() => nieuwePrintopdrachtInfo.EnergieTypeBrief)
.Select(() => joinedBriefType.Omschrijving).WithAlias(() => nieuwePrintopdrachtInfo.TypeBrief)
.Select(() => joinedVerzendModus.Omschrijving).WithAlias(() => nieuwePrintopdrachtInfo.VerzendModus)
.Select(() => joinedVerzendModus.Omschrijving).WithAlias(() => nieuwePrintopdrachtInfo.BestemmelingVerzendModus)
.Select(() => joinedBriefBestemmeling.BriefBestemmelingenId).WithAlias(() => nieuwePrintopdrachtInfo.BestemmelingId)
.Select(() => joinedBestemmelingType.Omschrijving).WithAlias(() => nieuwePrintopdrachtInfo.BestemmelingContactpersoonType)
.Select(() => joinedBriefBestemmeling.BestemmelingElektriciteit).WithAlias(() => nieuwePrintopdrachtInfo.BestemmelingElek)
.Select(() => joinedBriefBestemmeling.BestemmelingGas).WithAlias(() => nieuwePrintopdrachtInfo.BestemmelingGas)
.Select(() => joinedBriefBestemmeling.BinnenLand).WithAlias(() => nieuwePrintopdrachtInfo.BestemmelingBinnenLand)
.Select(() => joinedVerbruiksAdres.Land).WithAlias(() => nieuwePrintopdrachtInfo.LandVerbuiksadres)
.Select(Projections.Property(() => joinedContactpersoon.ContactpersoonId).As("BestemmelingContactPersoon.ContactPersoonId"))
.Select(Projections.Property(() => joinedContactpersoonType.Omschrijving).As("BestemmelingContactPersoon.TypeContactPersoon"))
.Select(Projections.Property(() => joinedContactpersoon.VoorNaam).As("BestemmelingContactPersoon.VoorNaam"))
.Select(Projections.Property(() => joinedContactpersoon.Naam).As("BestemmelingContactPersoon.Naam"))
.Select(Projections.Property(() => joinedContactpersoon.Straat).As("BestemmelingContactPersoon.Straat"))
.Select(Projections.Property(() => joinedContactpersoon.HuisNr).As("BestemmelingContactPersoon.HuisNummer"))
.Select(Projections.Property(() => joinedContactpersoon.BusNr).As("BestemmelingContactPersoon.BusNummer"))
.Select(Projections.Property(() => joinedContactpersoon.Gemeente).As("BestemmelingContactPersoon.Gemeente"))
.Select(Projections.Property(() => joinedContactpersoon.PostCode).As("BestemmelingContactPersoon.PostCode"))
.Select(Projections.Property(() => joinedContactpersoon.Appartement).As("BestemmelingContactPersoon.Appartement"))
.Select(Projections.Property(() => joinedContactpersoon.Verdieping).As("BestemmelingContactPersoon.Verdieping"))
.Select(Projections.Property(() => joinedContactpersoon.Telefoon1).As("BestemmelingContactPersoon.Telefoon1"))
.Select(Projections.Property(() => joinedContactpersoon.Telefoon2).As("BestemmelingContactPersoon.Telefoon2"))
.Select(Projections.Property(() => joinedContactpersoon.FAXNr).As("BestemmelingContactPersoon.Fax"))
.Select(Projections.Property(() => joinedContactpersoon.Email).As("BestemmelingContactPersoon.Email"))
.Select(Projections.Property(() => joinedContactpersoon.DatumCreatie).As("BestemmelingContactPersoon.DatumCreatie"))
.Select(Projections.Property(() => joinedContactpersoon.UserCreatie).As("BestemmelingContactPersoon.UserCreatie"))
.Select(Projections.Property(() => joinedContactpersoon.DatumUpdate).As("BestemmelingContactPersoon.DatumUpdate"))
.Select(Projections.Property(() => joinedContactpersoon.UserUpdate).As("BestemmelingContactPersoon.UserUpdate"))
.Select(Projections.Property(() => joinedContactpersoon.AdresBijTeWerken).As("BestemmelingContactPersoon.IsAdresBijTeWerken"))
.Select(Projections.Property(() => joinedContactpersoon.Titel).As("BestemmelingContactPersoon.Titel"))
.Select(Projections.Property(() => joinedContactpersoon.NietBesteldeBrief).As("BestemmelingContactPersoon.NietBesteldeBrief"))
.Select(Projections.Property(() => joinedContactpersoon.Land).As("BestemmelingContactPersoon.Land"))
.Select(Projections.Property(() => joinedContactpersoon.ContactpersoonAlsAanbrengerGebruikt).As("BestemmelingContactPersoon.ContactPersoonIdAlsAanbrenger"))
.Select(Projections.Property(() => joinedContactpersoon.ContactpersoonIsBetrokken).As("BestemmelingContactPersoon.ContactPersoonIsBetrokken"))
.Select(Projections.Property(() => joinedContactpersoon.NietAfgehaaldeBrief).As("BestemmelingContactPersoon.NietAfgehaaldeBrief"))
.Select(Projections.Property(() => joinedContactpersoonTaal.Omschrijving).As("BestemmelingContactPersoon.Taal"))
.Select(Projections.Property(() => joinedProfielGroep.Omschrijving).As("BestemmelingContactPersoon.IngegevenDoor"))
.Select(Projections.Property(() => joinedEan.Energietype).As("BestemmelingContactPersoon.EnergieType"))
.Select(Projections.Property(() => joinedVerbruiksVerantw.ToewijzigingVerbruiksVerantwoordelijkeId).As("BestemmelingContactPersoon.VerbruiksVerantwoordelijkeId")));
Да, я знаю, что это беспорядок. Теперь, когда вы сделали это так, вы с радостью узнаете, что мы почти там. Это код, который я использую для возврата результатов (это является общим и использует DeepTransform, который я нашел here)
protected IEnumerable<TR> GetDeepTransformedPagedList<T, TR>(IQueryOver<T, T> query) where TR : class
{
PagingSettings.Count = query.Clone().Select(Projections.CountDistinct(PagingSettings.PropertyNameToCountOn)).FutureValue<int>().Value;
query = query.TransformUsing(new DeepTransformer<TR>());
if (PagingSettings.Enabled)
{
var pagedQuery = query.Skip(GetPagingStartRowIndex()).Take(PagingSettings.PageSize);
return pagedQuery.List<TR>();
}
return query.List<TR>();
}
EDIT
После полезный пост Радим Кёлера я узнал что группа не поможет мне с моей проблемой. Вот почему я объясню настоящую проблему. В коде предыдущий запрос строится и расширяется с помощью Пропуска & Взять для подкачки. В моей ситуации я получаю 50 результатов при выполнении запроса. Эти 50 результатов содержат дубликаты и должны быть сгруппированы по UitgaandeBriefId. Вот почему оригинальные разработчики написали этот код, который выполняется после возвращения результатов из БД.
ILookup<int, IEnumerable<NieuwePrintopdrachtenInfo>> groupedbrieven =
(from tbInfo in brieven
group tbInfo by tbInfo.UitgaandeBriefId into g
let UitgaandeBriefId = g.Key
let Group = g as IEnumerable<NieuwePrintopdrachtenInfo>
select new { UitgaandeBriefId, Group })
.ToLookup(result => result.UitgaandeBriefId, result => result.Group);
Этот код по-прежнему работает, но приводит к получению только 32 результатов. Это приводит к тому, что мои страницы никогда не содержат 50 результатов. Первоначальный разработчик использовал подкачку на стороне сервера вместо того, чтобы делать это в БД, поэтому у него никогда не было этой проблемы (производительность была мудрой, это была огромная проблема). Вот почему я реорганизовал его так, чтобы он выполнялся намного быстрее, но это приводит к тому, что не получается получить 50 результатов. Я предполагаю, что мне нужно добавить четкий текст, но я не знаю, как это сделать, чтобы работать в NHibernate, так как я привык работать с EntityFramework.
Спасибо за ваш ответ. Это очень помогло мне. Но, похоже, группировка на все не дает мне результата, которого я хочу. Использование SelectGroup работает, но, похоже, не исправляет мою ситуацию. Я обновлю свой вопрос, чтобы объяснить это. – Beejee
Также я попробовал ваш метод расширения. Это выглядит лучше, чем то, что я использовал. Проблема в том, что теперь я получаю NullReferenceExceptions. Как обычно, ошибка ocurs в той части, где выполняется запрос, поэтому поиск реальной проблемы - это боль в ... Я начал отладку метода ParseProperty, и похоже, что «тело» фактически имеет нулевое значение. Я что-то упускаю? – Beejee
K выглядит так, как будто я смог его исправить. Я думаю, что ваша версия чересчур чередована. Я добавил некоторые дополнительные материалы, чтобы проверить «NodeType», и когда это «ExpressionType.Convert», я использую это как свое тело »((UnaryExpression) expression.Body) .Operand as MemberExpression« Теперь работает как шарм. Теперь мне нужно только вернуть правильные результаты – Beejee