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?
Related
I have to following LINQ code:
var variable1 = _entitiesContext.Table1
.Include("Table2")
.Include("Table3")
.Include("Table4")
.Join(_entitiesContext.Table2, t1 => t1.F_ID, t2 => t2.F_ID, (tbl1, tbl2) => new { tbl1, tbl2 })
.SelectMany(j => j.tbl2.Table3.Select(t3 => new
{
j.tbl2.F_ID,
j.tbl2.F_ZGP_No,
j.tbl1.F_NAME,
j.tbl1.K_CODE,
t3.Table4.Name,
t3.Table4.LEI,
}))
.Distinct()
.OrderBy(s => s.F_ID)
.ThenBy(s => s.Name)
.ToList();
How can I read it like a SQL statement? I don't understand the workflow about the .Includes.
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.
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>();
I have three tables. One is the master table: TableA. One table is referenced by TableA called ReferencedTable and lastly a lookup table referenced by ReferencedTable.
I have this query that returns the ten most recent objects as:
TableADTO TableAlias = null;
LookupTableDTO LookupTableAlias = null;
ReferencedDTO ReferencedAlias = null;
dtos = session.QueryOver(() => TableAlias)
.JoinAlias(() => TableAlias.Object, () =>ReferencedAlias)
.JoinAlias(() => ReferencedAlias.ObjectType, () => LookupTableAlias)
.Where(() => ReferencedAlias.PersonId == user.Id &&
(LookupTableAlias.Id != INVOICE_ID ||
LookupTableAlias.Id != FINANCIAL_ID) &&
TableAlias.Status == NEW_STATUS_FLAG &&
ReferencedAlias.ReceivedDate < DateTime.Now)
.Take(10)
.List()
.Select(dto=>
new AbreviatedDTO
{
Id = dto.Referenced.Id,
Field1 = dto.Field1,
Priority = dto.Referenced.Priority,
ReceivedDate = dto.Referenced.ReceivedDate,
Field1 = dto.Referenced.Field1,
Type = dto.Referenced.Lookup.TypeCode,
Status = dto.Status
}).ToList();
This works as expected. However, I thought the the transformation below would work too. It does bring 10 objects but the objects have all default values and are not populated (e.g. AbreviatedDTO.ReceivedDate = DateTime.Minimum). Am I doing something wrong with the QueryOver?
Any help would be appreciated.
Bill N
TableDTO TableAlias = null;
LookupTableDTO LookupTableAlias = null;
ReferencedDTO ReferencedAlias = null;
dtos = session.QueryOver(() => TableAlias)
.JoinAlias(() => TableAlias.Object, () =>ReferencedAlias)
.JoinAlias(() => ReferencedAlias.ObjectType, () => LookupTableAlias)
.Where(() => ReferencedAlias.PersonId == user.Id &&
(LookupTableAlias.Id != INVOICE_ID ||
LookupTableAlias.Id != FINANCIAL_ID) &&
TableAlias.Status == NEW_STATUS_FLAG &&
ReferencedAlias.ReceivedDate < DateTime.Now)
.SelectList(list => list
.Select(x => TableAlias.Field1)
.Select(x => ReferencedAlias.Id)
.Select(x => ReferencedAlias.Field1)
.Select(x => ReferencedAlias.ReceivedDate)
.Select(x => ReferencedAlias.Priority)
.Select(x => LookupTableAlias.TypeCode))
.TransformUsing(Transformers.AliasToBean<AbreviatedDTO>())
.Take(10)
.List<AbreviatedDTO>()
you'll need to define an alias for each selected field same as the propertyname in the resulting dto
AbreviatedDTO alias = null;
// in query
.SelectList(list => list
.Select(() => TableAlias.Field1).WithAlias(() => alias.Field1)
I have a query in Nhibernate QueryOver which brings back a collection of episode objects (episode being a spell of care) which in turn has a collection of episode statuses as a property of each episode. However I want to change this so that each episode only brings back the latest status update for that episode instead of all of them.
The SQL to do this is as follows:
SELECT *
FROM DIPEpisode e
INNER JOIN DIPEpisodeStatus s on s.EpisodeID = e.SequenceID
WHERE e.ClientID = '1000001'
AND s.SequenceID IN (
SELECT TOP 1 SequenceID
FROM DIPEpisodeStatus s
WHERE s.EpisodeID = e.SequenceID
ORDER BY StatusRecordedDate DESC
)
I have written the following query which gives me almost exactly what I need
var statuses =
QueryOver.Of<DIPEpisodeStatus>()
.OrderBy(x => x.StatusRecordedDate).Desc
.Select(x => x.Id).Take(1);
DIPEpisodeStatus statusAlias = null;
return
session.QueryOver<DIPEpisode>()
.JoinQueryOver(x => x.DIPEpisodeStatuss, () => statusAlias)
.Fetch(x => x.AgencyID).Eager
.Fetch(x => x.DIPEpisodeStatuss).Eager
.Where(e => e.ClientID.Id == this.clientId)
.WithSubquery.WhereProperty(x => x.Id).Eq(statuses)
.List();
This generates the following SQL:
SELECT *
FROM DIPEpisode this_
inner join DIPEpisodeStatus statusalia1_
on this_.SequenceID = statusalia1_.EpisodeID
WHERE statusalia1_.ClientID = '1000001' /* #p0 */
and statusalia1_.SequenceID = (SELECT TOP (1 /* #p1 */) this_0_.SequenceID as y0_
FROM DIPEpisodeStatus this_0_
ORDER BY this_0_.StatusRecordedDate desc)
As you can see, the only thing missing is the where clause from the subquery. What changes do I need to make to the query in order to generate this extra where clause and pull back only the most recent status update?
Thanks
Ben
the collection DIPEpisodeStatuss is always initialized with all entities because it would break changetracking otherwise. you could either define a filter for the collection or return a DTO with what you want. Also the fetch will be ignored because it can not eager load and filter in one sql statement.
NHibernate filters are explained here
defining Filters in FNH
how it would be done with a DTO
// assuming SequneceID and StatusRecordedDate correlates
var subquery = QueryOver.Of<DIPEpisode>()
.Where(e => e.ClientID.Id == this.clientId)
.JoinAlias(e => e.DIPEpisodeStatuss, () => statusAlias)
.Select(Projections.Max(() => statusAlias.SequenceID));
// or as in question
var subquery = QueryOver.Of<DIPEpisode>()
.Where(e => e.ClientID.Id == this.clientId)
.JoinAlias(e => e.DIPEpisodeStatuss, () => statusAlias)
.OrderByDescending(() => statusAlias.StatusRecordedDate)
.Select(() => statusAlias.SequenceID)
.Take(1);
DIPEpisodeDto dto = null;
DIPEpisodeStatus statusAlias = null;
return session.QueryOver<DIPEpisode>()
.Where(e => e.ClientID.Id == this.clientId)
.JoinQueryOver(e => e.DIPEpisodeStatuss, () => statusAlias)
.WithSubquery.WhereProperty(estatus => estatus.Id).Eq(statuses)
.SelectList(list => list
.Select(e => e.Whatever).WithAlias(() => dto.Whatever)
.Select(() => statusAlias.SquenceId).WithAlias(() => dto.StatusId)
...
)
.TransFormUsing(Transformers.AliasToBean<DIPEpisodeDto>())
.List();
or using LINQ
var query = from e in session.Query<DIPEpisode>()
from s in e.DIPEpisodeStatuss
where e.ClientID.Id == this.clientId
where s.Id == (
from e2 in session.Query<DIPEpisode>()
from s2 in e2.DIPEpisodeStatuss
orderby s2.StatusRecordedDate descending
select s2.Id)
.First()
select new DIPEpisodeDto
{
e.Prop1,
Status = s,
};
return query.List<DIPEpisodeDto>();