Why does Projections.SubQuery messes up the rest of the query? - nhibernate

I want to get a following query using QueryOver
select
cg.CoverageGrpId,
SUM(cp.PremiumDueAmt) + SUM(cf.PremiumDueAmt) as TotalPremium,
SUM(pa.PaymentAllocAmt) as AllocatedAmount, p.ClientPolicyId,
(SELECT MAX(c2.CvrgExpDt) FROM Coverage c2 where c2.CoverageGrpId = cg.CoverageGrpId) as CoverageExpDate,
(SELECT MIN(c3.CvrgEffDt) FROM Coverage c3 where c3.CoverageGrpId = cg.CoverageGrpId) as CoverageEffDate
from dbo.vw_D_CoverageGroup cg
inner join dbo.vw_D_Batch b on b.PremCvrgBatchId = cg.PremCvrgBatchId
inner join dbo.vw_D_ClientPolicy p on p.ClientPolicyId = cg.ClientPolicyId
inner join dbo.vw_D_Bid bd on bd.BidId = p.BidId
inner join dbo.vw_D_CoverageGroupRow cgr on cgr.CoverageGrpId = cg.CoverageGrpId
inner join dbo.vw_D_Coverage c on c.CoverageGrpRowId = cgr.CoverageGrpRowId
left outer join dbo.vw_D_CoveragePremium cp on c.CoverageId = cp.CoverageId
left outer join dbo.vw_D_CoverageFee cf on cf.CoverageId = cp.CoverageId
left outer join dbo.vw_D_PaymentAllocation pa on pa.CoverageGrpId = cg.CoverageGrpId
where c.PrimaryInsuredId = 701112800 and b.BatchTypeCd = 'INDV'
group by cg.CoverageGrpId, p.ClientPolicyId
order by cg.CoverageGrpId, p.ClientPolicyId
Following is QueryOver that gets messed up once I add commented part.
var dto = new InsuredCoveragePayments();
Coverage coverage = null;
CoverageGroup coverageGroup = null;
CoverageGroupRow coverageGroupRow = null;
Batch batch = null;
PaymentAllocation paymentAllocation = null;
CoveragePremium coveragePremium = null;
CoverageFee coverageFee = null;
ClientPolicy clientPolicy = null;
Bid bid = null;
var l = _session.QueryOver<CoverageGroup>(() => coverageGroup)
.JoinAlias(cg => cg.Batch, () => batch)
.JoinAlias(cg => cg.ClientPolicy, () => clientPolicy)
.JoinAlias(cg => clientPolicy.Bid, () => bid)
.JoinAlias(cg => cg.PaymentAllocations, () => paymentAllocation, JoinType.LeftOuterJoin)
.JoinQueryOver(cg => cg.CoverageGroupRows, () => coverageGroupRow)
.JoinQueryOver(cgr => cgr.Coverages, () => coverage)
.JoinAlias(c => c.Premium, () => coveragePremium, JoinType.LeftOuterJoin)
.JoinAlias(c => c.Fees, () => coverageFee, JoinType.LeftOuterJoin)
.Where(x => coverage.PrimaryInsured.Id == 701112800)
.SelectList(list =>
list.Select(Projections.Group<CoverageGroup>(x => x.Id))
.WithAlias(() => dto.CoverageGroupId)
.Select(Projections.Group<ClientPolicy>(x => clientPolicy.PolicyNumber))
.WithAlias(() => dto.ClientPolicyNumber)
.Select(Projections.Sum<CoveragePremium>(x => coveragePremium.Amount))
.WithAlias(() => dto.PremiumAmount)
.Select(Projections.Sum<CoverageFee>(x => coverageFee.Amount))
.WithAlias(() => dto.FeeAmount)
.Select(Projections.Sum<PaymentAllocation>(x => paymentAllocation.AllocatedAmount))
.WithAlias(() => dto.AllocatedAmount))
//this messes the query up, it removes all 'select' parts and adds only subquery
//.Select(Projections.SubQuery(
// QueryOver.Of<Coverage>()
// .Where(c => c.CoverageGroup.Id == coverageGroup.Id)
// .SelectList(cl =>
// cl.SelectMin(c => c.CoverageEffectiveDates.Start.Value)
// .WithAlias(() => dto.CoverageFrom))))
//.Select(Projections.SubQuery
// (QueryOver.Of<Coverage>()
// .Where(c => c.CoverageGroup.Id == coverageGroup.Id)
// .SelectList(cl2 =>
// cl2.SelectMax(c => c.CoverageEffectiveDates.End.Value)
// .WithAlias(() => dto.CoverageTo))))
.TransformUsing(new AliasToBeanResultTransformer(typeof(InsuredCoveragePayments)))
.List<InsuredCoveragePayments>();
NHibernate generated output
Without SubQuery
SELECT this_.CoverageGrpId as y0_,
clientpoli2_.Year as y1_,
clientpoli2_.ClientNumber as y2_,
clientpoli2_.BidOptionNumber as y3_
sum(coveragepr7_.PremiumDueAmt) as y4_,
sum(coveragefe8_.PremiumDueAmt) as y5_,
sum(paymentall4_.PaymentAllocAmt) as y6_
FROM vw_D_CoverageGroup this_
inner join vw_D_CoverageGroupRow coveragegr5_ on this_.CoverageGrpId=coveragegr5_.CoverageGrpId
inner join vw_D_Coverage coverage6_ on coveragegr5_.CoverageGrpRowId=coverage6_.CoverageGrpRowId
left outer join vw_D_CoverageFee coveragefe8_ on coverage6_.CoverageId=coveragefe8_.CoverageId
left outer join vw_D_CoveragePremium coveragepr7_ on coverage6_.CoverageId=coveragepr7_.CoverageId
left outer join vw_D_PaymentAllocation paymentall4_ on this_.CoverageGrpId=paymentall4_.CoverageGrpId
inner join vw_D_Batch batch1_ on this_.PremCvrgBatchId=batch1_.PremCvrgBatchId
inner join vw_D_ClientPolicy clientpoli2_ on this_.ClientPolicyId=clientpoli2_.ClientPolicyId
inner join vw_D_Bid bid3_ on clientpoli2_.BidId=bid3_.BidId
WHERE coverage6_.PrimaryInsuredId = #p0
GROUP BY this_.CoverageGrpId, clientpoli2_.Year,clientpoli2_.ClientNumber,clientpoli2_.BidOptionNumber;
#p0 = 701112800 [Type: Int32 (0)]
With SubQuery (both uncommented)
SELECT
(SELECT max(this_0_.CvrgExpDt) as y0_
FROM vw_D_Coverage this_0_
WHERE this_0_.CoverageGrpId = this_.CoverageGrpId) as y0_
FROM vw_D_CoverageGroup this_
inner join vw_D_CoverageGroupRow coveragegr5_ on this_.CoverageGrpId=coveragegr5_.CoverageGrpId
inner join vw_D_Coverage coverage6_ on coveragegr5_.CoverageGrpRowId=coverage6_.CoverageGrpRowId
left outer join vw_D_CoverageFee coveragefe8_ on coverage6_.CoverageId=coveragefe8_.CoverageId
left outer join vw_D_CoveragePremium coveragepr7_ on coverage6_.CoverageId=coveragepr7_.CoverageId
left outer join vw_D_PaymentAllocation paymentall4_ on this_.CoverageGrpId=paymentall4_.CoverageGrpId
inner join vw_D_Batch batch1_ on this_.PremCvrgBatchId=batch1_.PremCvrgBatchId
inner join vw_D_ClientPolicy clientpoli2_ on this_.ClientPolicyId=clientpoli2_.ClientPolicyId
inner join vw_D_Bid bid3_ on clientpoli2_.BidId=bid3_.BidId
WHERE coverage6_.PrimaryInsuredId = #p0;#p0 = 701112800 [Type: Int32 (0)]
As you can see, when I uncomment the SubQuery, not only does it return other pieces in select, but it also only generates one subquery. Why?

Figured it out. In SubQuery parts, I had WithAlias at wrong place. It should look like this
var l = _session.QueryOver<CoverageGroup>(() => coverageGroup)
.JoinAlias(cg => cg.Batch, () => batch)
.JoinAlias(cg => cg.ClientPolicy, () => clientPolicy)
.JoinAlias(cg => clientPolicy.Bid, () => bid)
.JoinAlias(cg => cg.PaymentAllocations, () => paymentAllocation, JoinType.LeftOuterJoin)
.JoinQueryOver(cg => cg.CoverageGroupRows, () => coverageGroupRow)
.JoinQueryOver(cgr => cgr.Coverages, () => coverage)
.JoinAlias(c => c.Premium, () => coveragePremium, JoinType.LeftOuterJoin)
.JoinAlias(c => c.Fees, () => coverageFee, JoinType.LeftOuterJoin)
.Where(x => coverage.PrimaryInsured.Id == 701112800)
.SelectList(list =>
list
.Select(Projections.Group<CoverageGroup>(x => x.Id))
.WithAlias(() => dto.CoverageGroupId)
.Select(Projections.Group<ClientPolicy>(x => clientPolicy.PolicyNumber))
.WithAlias(() => dto.ClientPolicyNumber)
.Select(Projections.Sum<CoveragePremium>(x => coveragePremium.Amount))
.WithAlias(() => dto.PremiumAmount)
.Select(Projections.Sum<CoverageFee>(x => coverageFee.Amount))
.WithAlias(() => dto.FeeAmount)
.Select(Projections.Sum<PaymentAllocation>(x => paymentAllocation.AllocatedAmount))
.WithAlias(() => dto.AllocatedAmount)
.Select(Projections.SubQuery
(QueryOver.Of<Coverage>()
.Where(c => c.CoverageGroup.Id == coverageGroup.Id)
.SelectList(cl =>
cl.SelectMin(c => c.CoverageEffectiveDates.Start.Value))))
.WithAlias(() => dto.CoverageFrom)
.Select(Projections.SubQuery
(QueryOver.Of<Coverage>()
.Where(c => c.CoverageGroup.Id == coverageGroup.Id)
.SelectList(cl2 =>
cl2.SelectMax(c => c.CoverageEffectiveDates.End.Value))))
.WithAlias(() => dto.CoverageTo) )
.TransformUsing(new AliasToBeanResultTransformer(typeof(InsuredCoveragePayments)))
.List<InsuredCoveragePayments>();

Related

Multiple Conditions in Nhibernate Left Join

Please need some help converting this sql query to nhibernate
select a.ID, count(b.ID)
from appusers a
left join weeklytasks b on a.ID = b.TaskOwner and b.taskstatus = 1
group by a.ID
It's difficult to answer without knowing your entities, mappings, used technology(ICreteria API, QueryOver, Linq).
But I can suggest this solution using QueryOver:
AppUser ownerAlias = null;
WeeklyTask taskAlias = null;
var result = Session.QueryOver(() => taskAlias)
.JoinAlias(x => x.TaskOwner,
() => ownerAlias,
NHibernate.SqlCommand.JoinType.RightOuterJoin,
Restrictions.Where(() => taskAlias.Status == 1))
.SelectList(list => list
.SelectGroup(x => ownerAlias.Id)
.SelectCount(x => x.Id))
.List<object[]>();
or this:
var result = Session.QueryOver<WeeklyTask>()
.Where(x => x.Status == 1)
.Right.JoinQueryOver(x => x.TaskOwner)
.SelectList(list => list
.SelectGroup(x => x.TaskOwner.Id)
.SelectCount(x => x.Id))
.List<object[]>();
Please notice that in this approach your WeeklyTask entity must contains mapped reference to AppUser entity.

nHibernate join alias projecting some fields

I have the following query in nHibernate, which works really well.
Table1 table1Alias = null;
Table2 table2Alias = null;
Table3 table3Alias = null;
Table4 table4Alias = null;
Table5 table5Alias = null;
Table6 table6Alias = null;
var resultTable = session.QueryOver<Table1>()
.JoinAlias(x => x.Table2, () => table2Alias, NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.JoinAlias(() => table2Alias.Table3, () => itemDesctable3AliasriptionAlias, NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.JoinAlias(() => table2Alias.Table4, () => table4Alias, NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.JoinAlias(x => x.Table5, () => table5Alias, NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.JoinAlias(() => table5Alias.Table6, () => table6Alias, NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.Where(x => x.Id == inputId)
.TransformUsing(Transformers.DistinctRootEntity)
.SingleOrDefault();
the problem is, i suspect i'll run into performance issues because
some of the tables have a lot of columns.
So here's the question, let's say I only need 1 field from "Table 5", but
fields from the rest of the table, do i have to do manual projections for all tables? or is there a way to only do manual projection for one table but left the rest as is?

C# + LINQ - inner join

Table: one
Column (PK): employee_ssn
Column: employee_active bit
Table: two
Column (pk): date
Column (FK): employee_ssn
Column: total_income
Column: total_expenses
Working Linq code to sum total_income and total_expenses for the year, per employee:
var SumOfSections = db.two
.Select(x => x)
.Where(x => x.employee_ssn.Equals(xxxxxxxxx))
.Where(x => x.Date.Year.Equals(year))
.GroupBy(x => x.Date)
.Select(g => new
{
Total_Income = g.Sum(x => x.total_expenses),
Total_Expenses= g.Sum(x => x.total_income)
})
.ToArray();
I need to incorporate INNER JOIN to the above to only include active employees. Working SQL:
select two.total_income,total_expenses
from two
INNER JOIN one
ON one.SSN = two.SSN
WHERE one.Active = 1 AND two.Date='1/1/2014' AND two.SSN='xxxxxxxxx';
How can I modify my linq code to what my sql code is doing?
var SumOfSections = (from t in db.two
join o in db.one on t.employee_ssn equald o.employee_ssn
where t.employee_ssn = "xxxxxxxxx" && o.employee_active == true
group t by t.date into g
select new {
Total_Income = g.Sum(x => x.total_expenses),
Total_Expenses= g.Sum(x => x.total_income)
}).ToArray();
I used query syntax because it seems to be more readable.
You can also continue with the notation you are using:
var SumOfSections = db.two.Join(db.one, o=>o.employee_ssn, t=>t.employee_ssn, (o,t)=>new {One = o, Two = t)
.Select(x => x)
.Where(x => x.Two.employee_ssn.Equals(""))
.Where(x => x.Two.date.Year.Equals(1234))
.Where(x=> x.One.employee_active == true)
.GroupBy(x => x.Two.date)
.Select(g => new
{
Total_Income = g.Sum(x => x.Two.total_expenses),
Total_Expenses = g.Sum(x => x.Two.total_income)
})
.ToArray();

NHibernate Query subquery group by join back to main entity

Hello i'm trying to achieve the following SQL
SELECT this_.*
FROM WorkItems this_
WHERE this_.UserId = (
SELECT this_1_.y0_ as y0_
FROM
(
SELECT top 1 this_0_.UserId as y0_, count(this_0_.UserId) as y1_
FROM WorkItems this_0_
WHERE this_0_.StateId = 1 and this_0_.Type like 'Data'
GROUP BY this_0_.UserId
ORDER BY y1_ desc
) this_1_
);
so far i have manged to produce something fairly close. I'm missing the part where i just select out the userId.
heres the query so far
var subquery = QueryOver.Of<WorkItem>().Where(w => w.State == state)
.AndRestrictionOn(w => w.Type).IsLike(type, MatchMode.Exact)
.SelectList(list =>
list.SelectGroup(w => w.UserId)
.WithAlias(() => resultAlias.userId)
.SelectCount(w => w.UserId)
.WithAlias(() => resultAlias.count))
.OrderByAlias(() => resultAlias.count)
.Desc().Take(1);
var query =
CurrentSession.QueryOver<WorkItem>()
.WithSubquery
.WhereProperty(p => p.UserId)
.Eq(subquery);
Try this: -
var subquery = QueryOver.Of<WorkItem>().Where(w => w.State == state)
.AndRestrictionOn(w => w.Type).IsLike(type, MatchMode.Exact)
.SelectList(list => list.SelectGroup(w => w.UserId))
.OrderBy(Projections.Count<WorkItem>(x => x.UserId))
.Desc().Take(1);
var query = CurrentSession.QueryOver<WorkItem>()
.WithSubquery
.WhereProperty(p => p.UserId)
.Eq(subquery);

How to do this in nhibernate queryover

I need to do this in nhibernate QueryOver:
select distinct sc.* from [Security].[Commands] sc
inner join [Security].[SystemSubjects] ss on ss.Id = sc.Id
left outer join [Security].[SystemSubjectRoles] ssr on ssr.SystemSubjectId = ss.Id
left outer join [Security].[Roles] sr on sr.Id = ssr.RoleId
left outer join [Security].[UserRoles] ur on ur.IdRole = sr.Id
left outer join [Security].[User] su2 on su2.Id = ur.IdUser
left outer join [Security].SystemSubjectUsers ssu on ssu.SystemSubjectId = ss.Id
left outer join [Security].[User] su on su.Id = ssu.UserId
where (su2.Id = 1 or su.Id = 1)
So far I have done this:
var queryOverRoles = QueryOver.Of<Command>(() => cmdAlias)
.JoinAlias(() => cmdAlias.SystemSubjectRoles, () => ssRoleAlias, JoinType.LeftOuterJoin)
.JoinAlias(() => ssRoleAlias.Role, () => roleAlias, JoinType.LeftOuterJoin)
.JoinAlias(() => roleAlias.Users, () => userAlias, JoinType.LeftOuterJoin)
.JoinAlias(() => cmdAlias.SystemSubjectUsers, () => ssUserAlias, JoinType.LeftOuterJoin)
.JoinAlias(() => ssUserAlias.User, () => userAlias2, JoinType.LeftOuterJoin)
.TransformUsing(Transformers.DistinctRootEntity)
.Where(() => ssRoleAlias.SecurityPermission == SecurityPermission.Allow)
.And(() => (userAlias.Id == userId || userAlias2.Id == userId))
but this selects all (Select ) and I want only the Command object (select sc.).
If I try to add a projection to the query like this:
queryOverRole.Select(x=>x);
it throws this exception:
System.Exception was caught Message=Could not determine member
from x Source=NHibernate
StackTrace:
at NHibernate.Impl.ExpressionProcessor.FindMemberExpression(Expression
expression) in
d:\CSharp\NH\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line
189
at NHibernate.Criterion.QueryOver2.Select(Expression1[]
projections) in
d:\CSharp\NH\nhibernate\src\NHibernate\Criterion\QueryOver.cs:line
363
at Novatec.Persistence.Repositories.Implementations.UserRepository.GetAllowedUserCommands(Int32
userId) in
C:\Projects\EGrad\Main\Source\Novatec.E-Grad\Source\Novatec.Persistence\Repositories\Implementations\UserRepository.cs:line
140
at Novatec.Administracija.Services.Security.SecurityManager.AuthorizeUserAction(Int32
userId, String commandId) in
C:\Projects\EGrad\Main\Source\Novatec.E-Grad\Source\Novatec.Administracija.Services\Security\SecurityManager.cs:line
48
at Novatec.Framework.Infrastructure.Services.ServiceBase.ExecuteCommand(Int32
userId, String appId, ICommand
command) in
C:\Projects\EGrad\Main\Source\Novatec.E-Grad\Source\Novatec.Framework.Infrastructure\Services\ServiceBase.cs:line
94 InnerException:
Try this.... you need to specify which alias to select.
queryOverRole.Select(result => cmdAlias);