How to use datediff sql function in nHibernate? - c#

I am developing an application to test execution time SQL queries using different frameworks. I have some problem to write one of the queries using Fluent nHibernate. The query should return all employees that are older than 50 years. In some page I found the DateProjections class which I attach below.
public static class DateProjections
{
private const string DateDiffFormat = "datediff({0}, ?1, ?2)";
public static IProjection DateDiff(
string datepart,
Expression<Func<object>> startDate,
Expression<Func<object>> endDate)
{
// Build the function template based on the date part.
string functionTemplate = string.Format(DateDiffFormat, datepart);
return Projections.SqlFunction(
new SQLFunctionTemplate(NHibernateUtil.Int32, functionTemplate),
NHibernateUtil.Int32,
Projections.Property(startDate),
Projections.Property(endDate));
}
}
The function to get employees is the following:
public List<EmployeeAgeViewModel> GetEmployeesOlderThan50()
{
Person personAlias = null;
EmployeeAgeViewModel result = null;
var temp = _session.QueryOver<Employee>().JoinQueryOver(x => x.Person, () => personAlias).SelectList(
list => list
.Select(x => personAlias.FirstName).WithAlias(() => result.FirstName)
.Select(x => personAlias.LastName).WithAlias(() => result.LastName)
.Select(x => x.Gender).WithAlias(() => result.Gender)
.Select(x => x.BirthDate).WithAlias(() => result.BirthDate)
.Select(x => x.HireDate).WithAlias(() => result.HireDate)
.Select(DateProjections.DateDiff("yy", () => personAlias.Employee.BirthDate, () => DateTime.Now)).WithAlias(() => result.Age)
)
.TransformUsing(Transformers.AliasToBean<EmployeeAgeViewModel>())
.List<EmployeeAgeViewModel>();
return temp.ToList();
The problem is probably the way I am passing BirthDate property and DateTime.Now to DateDiff function. In the personAlias variable the Employee property is null - maybe I should assign it somehow before - any help will be appreciated.

Instead of personAlias.Employee.BirthDate you need to use an employeeAlias.
Your code with the necessary changes looks like this:
Person personAlias = null;
Employee employeeAlias = null;
EmployeeAgeViewModel result = null;
var temp = _session.QueryOver<Employee>(() => employeeAlias)
.JoinQueryOver(x => x.Person, () => personAlias)
.SelectList(
list => list
.Select(x => personAlias.FirstName).WithAlias(() => result.FirstName)
.Select(x => personAlias.LastName).WithAlias(() => result.LastName)
.Select(x => x.Gender).WithAlias(() => result.Gender)
.Select(x => x.BirthDate).WithAlias(() => result.BirthDate)
.Select(x => x.HireDate).WithAlias(() => result.HireDate)
.Select(DateProjections.DateDiff("yy", () => employeeAlias.BirthDate, () => DateTime.Now))
.WithAlias(() => result.Age)
)
.TransformUsing(Transformers.AliasToBean<EmployeeAgeViewModel>())
.List<EmployeeAgeViewModel>();
return temp.ToList();

Related

how multiple map in automapper

I recently met with an automapper. I have a question, how i can map multiple objects from my repostiory in one DTO.
public QuestionProfile()
{
CreateMap<Question, GrammarQuestionDTO>()
.ForMember(g => g.Question, q => q.MapFrom(source => source.Text)).ReverseMap();
CreateMap<List<GrammarQuestionDTO>, TestDTO>()
.ForMember(t => t.GrammarQuestion, g => g.MapFrom(source => source)).ReverseMap();
CreateMap<Question, AuditionQuestionDTO>()
.ForMember(a => a.Question, q => q.MapFrom(source => source.Text))
.ForMember(a => a.Url, q => q.MapFrom(source => source.AudioFile.Url)).ReverseMap();
CreateMap<List<AuditionQuestionDTO>, TestDTO>()
.ForMember(t => t.AuditionQuestion, a => a.MapFrom(source => source)).ReverseMap();
}
how can I map all these 4 objects?
public async Task<TestDTO> GenerateTest(LevelType level)
{
var grammarQuestions = await _questionRepository.GetGrammarQuestionAsync(level);
var auditionQuestions = await _questionRepository.GetAuditionQuestionAsync(level);
var essayTopic = await _questionRepository.GetEssayTopicAsync(level);
var speakingTopic = await _questionRepository.GetSpeakingTopicAsync(level);
var test = _mapper.Map<TestDTO>(grammarQuestions);
test = _mapper.Map(test, auditionQuestions); //there will be a conversion error
return _mapper.Map<TestDTO>(grammarQuestions);
}
You need to map it without list, just map it one to one and AutoMapper will handle the collections:
CreateMap<AuditionQuestionDTO, TestDTO>()
.ForMember(t => t.AuditionQuestion,
a => a.MapFrom(source => source.<PropertyName>)).ReverseMap();
And then on the map you should:
test = _mapper.Map<List<AuditionQuestionDTO>>(test, auditionQuestions);

NHibernate QueryOver with SelectList

I have multiple queries against one table. As not all columns/properties are needed I specify the columns with the help of select list. Take the following method as example. This method is working
public IEnumerable<ResultDto> GetEntityAsDto(eStatusBinderProduktion fromState, eStatusBinderProduktion toState)
{
EntityClass entityAlias = null;
ResultDto resultAlias = null;
var query = Session.QueryOver<EntityClass>(() => entityAlias)
.Where(() => entityAlias.ProduktionStatus >= (byte)fromState)
.And(() => entityAlias.ProduktionStatus <= (byte)toState);
query.SelectList(list => list
.Select(() => entityAlias.PrimaryID).WithAlias(() => resultAlias.PrimaryID)
.Select(() => entityAlias.SecondaryID).WithAlias(() => resultAlias.SecondaryID)
);
return query.TransformUsing(Transformers.AliasToBean<ResultDto>())
.List<ResultDto>();
}
As I need to define the SelectList in multiple methods, I tried to to move the SelectList into a separate method.
The following code is not working, NHibernate throws the exception
NHibernate.QueryException: 'could not resolve property: entity.PrimaryID of: MyProjectNamespace.DAL.Interfaces.Entities.EntityClass'
"
public IEnumerable<ResultDto> GetEntityAsDto(eStatusBinderProduktion fromState, eStatusBinderProduktion toState)
{
EntityClass entityAlias = null;
ResultDto resultAlias = null;
var query = Session.QueryOver<EntityClass>(() => entityAlias)
.Where(() => entityAlias.ProduktionStatus >= (byte)fromState)
.And(() => entityAlias.ProduktionStatus <= (byte)toState);
MapPropertiesOfEntityToResult(entityAlias, resultAlias, query);
return query.TransformUsing(Transformers.AliasToBean<ResultDto>())
.List<ResultDto>();
}
private void MapPropertiesOfEntityToResult(EntityClass entity, ResultDto resultAlias, IQueryOver<EntityClass, EntityClass> query)
{
query.SelectList(list => list
.Select(() => entity.PrimaryID).WithAlias(() => resultAlias.PrimaryID)
.Select(() => entity.SecondaryID).WithAlias(() => resultAlias.SecondaryID)
);
}
Additional information:
- The mappings are correct
- table is filled with test data
We do not need alias for filling SelectList. We can profit from the Type parameters coming with IQueryOver<TRoot,TSubType>:
//private void MapPropertiesOfEntityToResult(EntityClass entity
// , ResultDto resultAlias, IQueryOver<EntityClass, EntityClass> query)
private void MapPropertiesOfEntityToResult( // no need for entity
ResultDto resultAlias, IQueryOver<EntityClass, EntityClass> query)
{
query.SelectList(list => list
//.Select(() => entity.PrimaryID).WithAlias(() => resultAlias.PrimaryID)
//.Select(() => entity.SecondaryID).WithAlias(() => resultAlias.SecondaryID)
.Select(entity => entity.PrimaryID).WithAlias(() => resultAlias.PrimaryID)
.Select(entity => entity.SecondaryID).WithAlias(() => resultAlias.SecondaryID)
);
}
The entity is now a parameter of the passed Function and its type is coming from IQueryOver definition

EF Dynamic Field Select using LINQ

I have the following select:
var sortedCodes = Codes
.Where(c => c.Active)
.OrderByDescending(x => x.SortOrder)
.Select(b => new { b.Display, b.NumericCode, b.SortOrder })
.Distinct()
.ToList();
The table Code has many columns such as NumericCode, TextCode, AlphaCode, ThreeCode, FourCode, FiveCode. I am using this table to build selects in my UI. Is there a way I can create some dynamic code so I can pass in the column name to use for the value?
The above select would look like this:
.Select(b => new { b.Display, "TextCode", b.SortOrder })
I was thinking I could use an Expression, but I do not think this is exactly what I need as it is actually printing the lambda as the value.
var arg = Expression.Parameter(typeof(Code), "b");
var body = Expression.Property(arg, valueColumn);
var lambda = Expression.Lambda<Func<Code, string>>(body, arg);
var sortedCodes = Codes
.Where(c => c.Active)
.OrderByDescending(x => x.SortOrder)
.Select(b => new { b.Display, Value=lambda, b.SortOrder })
.Distinct()
.ToList();

Nhibernate Group By and Alias To Bean

I have been struggling to get an old query translated to Nhibernate.
We are upgrading an old project from Nhibernate 2 to the latest version.
I am using the QueryOver syntax since Linq wasn't an option because of the complexity of the queries (advice of a colleague).
I want to query the DB (Oracle) to get some results which have to be grouped.
As result I need a grouped collection of my DTO. I also noticed that nhibernate has trouble translating to a DTO with complex properties (nested DTO's)
To fix this I found this topic. This works great but I am not a fan of the magic strings...
I will add some code snippets of how my monster query is looking at this moment.
Problem is I can't seem to figure out how to add a group by without breaking everything else. So I would want to group on a property but still have the DTO in my results. Something like:
ILookup<int,IEnumerable<NieuwePrintopdrachtenInfo>>
Any help would be welcome.
Sorry the variables and classes are in Dutch -_-
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);
This is only the beginning. Here comes the part to filter the results (when needed).
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());
}
Then I got the part to select the stuff I need and translate it into the 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")));
Yeah I know it is a mess. Now that you made it this far, you'll be happy to know we are almost there. This is the code I use to return the results (It is generic and uses the DeepTransform which I found 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
After the helpful post of Radim Köhler I found out that a group by won't help me with my problem. That's why I'll explain the real problem.
In code the previous query is build and extended with a Skip & Take for paging purpose. In my situation I get 50 results when executing the query.
These 50 results contain duplicates and need to be grouped by UitgaandeBriefId.
That's why the original developers wrote this code that is executed once the results are back from the DB.
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);
This code still works but results in getting only 32 results. This causes my pages to never contain 50 results. The original developer used server side paging instead of doing it on the DB so he never got this problem (performance wise this was a huge problem). That's why I refactored it so it would execute a lot faster, but this results in not getting exectly 50 results.
I guess I'll need to add a distinct then but I have no clue how I get this to work in NHibernate since I am used to work with EntityFramework.
In general, if we want to change our projection to be using GROUP BY, we have to change all "SELECT" parts to be either part of GROUP BY or SUM, MIN ...
We can do it with this kind of syntax
// firstly
// the original part from the question above
baseQuery.SelectList(list => list
...
.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"))
...
// changed, to use GROUP BY
baseQuery.SelectList(list => list
...
.SelectGroup(() => joinedBriefBestemmeling.BinnenLand)
.WithAlias(() => nieuwePrintopdrachtInfo.BestemmelingBinnenLand)
.SelectGroup(() => joinedVerbruiksAdres.Land)
.WithAlias(() => nieuwePrintopdrachtInfo.LandVerbuiksadres)
.Select
(Projections.Alias
(Projections.GroupProperty
(Projections.Property(() => joinedContactpersoon.ContactpersoonId))
, "BestemmelingContactPersoon.ContactPersoonId"))
.Select
(Projections.Alias
(Projections.GroupProperty
(Projections.Property(() => joinedContactpersoonType.Omschrijving))
, "BestemmelingContactPersoon.TypeContactPersoon"))
...
So, now we have the GROUP BY (instead of just a SELECT) replacing the original code. But we can do more, we can introduce these (just a quick version) Extension methods (just a light version, really - but working)
public static class Extensions
{
public static NHibernate.Criterion.Lambda.QueryOverProjectionBuilder<T> GroupByProperty<T>(
this NHibernate.Criterion.Lambda.QueryOverProjectionBuilder<T> builder,
System.Linq.Expressions.Expression<Func<object>> propertyExpression,
System.Linq.Expressions.Expression<Func<object>> aliasExpression)
{
var alias = aliasExpression.ParseProperty();
var propertyProjection = Projections.Property(propertyExpression);
var groupProjection = Projections.GroupProperty(propertyProjection);
var withAliasProjection = Projections.Alias(groupProjection, alias);
builder.Select(withAliasProjection);
return builder;
}
public static string ParseProperty<TFunc>(this System.Linq.Expressions.Expression<TFunc> expression)
{
var body = expression.Body as System.Linq.Expressions.MemberExpression;
if (body.IsNull())
{
return null;
}
string propertyName = body.Member.Name;
ParseParentProperty(body.Expression as System.Linq.Expressions.MemberExpression, ref propertyName);
// change the alias.ReferenceName.PropertyName
// to just ReferenceName.PropertyName
var justAPropertyChain = propertyName.Substring(propertyName.IndexOf('.') + 1);
return justAPropertyChain;
}
static void ParseParentProperty(System.Linq.Expressions.MemberExpression expression, ref string propertyName)
{
if (expression.IsNull())
{
return;
}
// Parent.PropertyName
propertyName = expression.Member.Name + "." + propertyName;
ParseParentProperty(expression.Expression as System.Linq.Expressions.MemberExpression, ref propertyName);
}
}
And the above code could be made more readable and common, without any magic string
baseQuery.SelectList(list => list
...
.GroupByProperty(() => joinedBriefBestemmeling.BinnenLand)
,() => nieuwePrintopdrachtInfo.BestemmelingBinnenLand)
.GroupByProperty(() => joinedVerbruiksAdres.Land)
,() => nieuwePrintopdrachtInfo.LandVerbuiksadres)
.GroupByProperty(() => joinedContactpersoon.ContactpersoonId)
.() => nieuwePrintopdrachtInfo.BestemmelingContactPersoon.ContactPersoonId)
.GroupByProperty(() => joinedContactpersoonType.Omschrijving)
.() => nieuwePrintopdrachtInfo.BestemmelingContactPersoon.TypeContactPersoon)
...
NOTE IsNull() is also extension

Joins in nhibernate

I am using blow code for join in nhibernate, which is working fine. But i don't wants to use .List on both queries before join, i wants to use .List after join. I don't know nhibernate too much.. please provide me help that what i should make changes in below funciton to first join the data and then apply .List over it.
public IEnumerable<PGrp> GetSol()
{
_pGrpR = null;
_pGrp = null;
QueryOver<Phy, Phy> activePhyQuery = GetDataQuery();
var phyGrpR = _session.QueryOver(() => _pGrpR)
.Where(
Subqueries.WhereProperty<PGrpR>(p => _pGrpR.PhyId).In(
activePhyQuery))
.List<PGrpR>();
IList<PGrp> pGrps = _session.QueryOver(() => _pGrp)
.Where(x => !x.AC)
.List<PGrp>();
var newPGrps = pGrps
.Join(
pGrpR,
p => p.Id,
x => x.PGrpId,
(p, x) => p
).Distinct().OrderBy(x => x.Name);
return newPGrps;
}
Thanks
PGrpR pGrpR = null;
IList<PGrp> pGrps = _session.QueryOver(() => _pGrp)
.Where(x => !x.AC)
.JoinAlias(pgrps => pgrps.pGrpR, () => pGrpR) // Set real property name
.OrderBy(() => pGrpR.Name).Asc
.Select(Projections.Distinct(Projections.Property(() => pGrpR."PropertyForDistinct")))
.TransformUsing(Transformers.DistinctRootEntity)
.List<PGrp>();

Categories