NHibernate QueryOver join syntax for multiple tables - nhibernate

How would I rewrite this SQL using QueryOver? I'm not sure how QueryOver's join precedence and resolution works.
SELECT DISTINCT T1.*
FROM T1
LEFT JOIN T2
JOIN T3
ON T2.T3Key = T3.PrimaryKey
ON T1.PrimaryKey = T2.T1Key
LEFT JOIN T4
JOIN T5
ON T4.T5Key = T5.PrimaryKey
ON T1.PrimaryKey = T4.T1Key
WHERE T3.Criteria = #Criteria
OR T5.Criteria = #Criteria
http://www.sqlfiddle.com/#!3/affd13/5

Assuming you have all the relationships setup, it's a matter of setting up alias variable to use in the QueryOver...
T2 t2Alias = null;
T3 t3Alias = null;
T4 t4Alias = null;
T5 t5Alias = null;
int criteria = 1;
var results = Session.QueryOver<T1>()
.Left.JoinAlias(x => x.T2, () => t2Alias)
.Left.JoinAlias(() => t2Alias.T3, () => t3Alias)
.Left.JoinAlias(x => x.T4, () => t4Alias)
.Left.JoinAlias(() => t4Alias.T5, () => t5Alias)
.Where(Restrictions.Disjunction()
.Add(Restrictions.Where(() => t3Alias.Criteria == criteria))
.Add(Restrictions.Where(() => t5Alias.Criteria == criteria)))
.TransformUsing(Transformers.DistinctRootEntity)
.List();
I don't think you'll be able to nest those inner joins...but it looks like you'd get the same results with all left joins.

Related

Convert sql to linq with STRING_AGG

convert sql to linq that has STRING_AGG
SELECT
V.pkid,
V.[Name] AS VendorName,
SFTP.SFTP_Paths AS SFTP_Paths
FROM
dbo.Vendor V
LEFT OUTER JOIN (
SELECT
connected_to,
STRING_AGG(rootfolder, ', ') AS SFTP_Paths
FROM
dbo.FTP
WHERE
connected_to_type = 4 -- Vendor
GROUP BY
connected_to
) SFTP ON v.pkid = SFTP.connected_to
WHERE
V.active = 1
order by
V.[name]
This query returns the same sql query result.
Instead of STRING_AGG (rootfolder, ',') AS SFTP_Paths I used SFTP_Paths = string.Join(",", b.Select (c => c.rootfolder).ToArray()) for equivalence.
The rest of the query is understandable.
var query = vendorList.Join(lstFtp.Where(x => x.connected_to_type == 4).GroupBy(a => a.connected_to)
.Select(b => new
{
connected_to = b.Key,
SFTP_Paths = b.Select(c => c.rootfolder).ToList()
}).AsEnumerable()
.Select(b => new
{
connected_to = b.connected_to,
SFTP_Paths = string.Join(",", b.SFTP_Paths).ToArray()
}),
right => right.pkid,
left => left.connected_to,
(right, left) => new
{
V = right,
SFTP = left
}).Where(d => d.V.active == 1)
.Select(e => new
{
pkid = e.V.pkid,
VendorName = e.V.Name,
SFTP_Paths = e.SFTP.SFTP_Paths
})
.OrderBy(e => e.VendorName).ToList();

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?

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

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>();

How to use the group join result to join another tables using LINQ?

I am not able to use the result of group join and then further applying the join with other tables.
My SQL query is :
SELECT *
FROM
[dummy_database].[dbo].[MA] M
INNER JOIN
SN.dbo.A A ON A.ApplicantMAId = M.MAId
INNER JOIN
SN.dbo.SP SP ON SP.PropertyMAId = M.MAId
INNER JOIN
SN.dbo.MCC CC ON CC.MAId = m.MAId
INNER JOIN
SN.dbo.MLSTN T ON T.MAT_ID = M.MAId
INNER JOIN
(SELECT
MAX(MAT_DATE) AS MaxDate,
MAT_ID
FROM
[SN].[dbo].[MLSTN]
GROUP BY
MAT_ID) Q ON Q.MAT_ID = M.MAId
and what I have done so far is:
var q = (from ml in context.MLSTN
group ml by ml.MAT_ID into g
let maxdate = g.Max(date => date.MAT_DATE)
select new
{
MortgId = g.Key,
TrackingDate = g.FirstOrDefault(val => val.MAT_DATE == maxdate).MAT_DATE
}
);
but now this result is not at all further used by me to create a join with other tables. I want to ask how to join further? Any clue?
You need something like this:
var groups = context.MLSTN
.GroupBy(x => x.MAT_ID)
.Select(g => new
{
MAT_ID = g.Key,
MaxDate = g.Max(date => date.MT_DATE)
});
var result = context.MA
.Join(context.A,
m => m.MA_ID,
a => a.MA_ID,
(m, a) => new
{
MA = m,
A = a
})
.Join(context.SP,
x => x.MA.MAId,
sp => sp.PropertyMAId,
(x, sp) => new
{
MA = x.MA ,
A = x.A,
SP = sp
})
.Join(context.MCC,
x => x.MA.MAId,
cc => cc.MAId,
(x, cc) => new
{
MA = x.MA ,
A = x.A,
SP = x.SP,
MCC = cc
})
.Join(context.MLSTN,
x => x.MA.MAId,
t => t.MAT_ID,
(x, t) => new
{
MA = x.MA ,
A = x.A,
SP = x.SP,
MCC = x.MCC,
MLSTN = t
})
.Join(groups,
x => x.MA.MAId,
g => g.MAId,
(x, g) => new
{
MA = x.MA ,
A = x.A,
SP = x.SP,
MCC = x.MCC,
MLSTN = t,
MLSG = g
});

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);