NHibernate JoinQueryOver and Lazy Loading - c#

I have a query
var query = _session.QueryOver<TEntity>().JoinQueryOver<PropertyMultTable>(p => p.Properties).Where(propertyPredicate).List();
this query generates the next SQL
select this_.BaseEntity_id as BaseId0_1_ ,
this_1_.Label as Label0_1_ ,
this_1_.Description as Descript3_0_1_ ,
this_1_.CreatedDate as CreatedD4_0_1_ ,
this_.Width as Width2_1_ ,
this_.Height as Height2_1_ ,
this_.Duration as Duration2_1_ ,
propertymu1_.id as id4_0_ ,
propertymu1_.Name as Name4_0_ ,
propertymu1_1_.DateTimeValue as DateTime2_5_0_ ,
propertymu1_2_.IntegerValue as IntegerV2_6_0_ ,
propertymu1_3_.DecimalValue as DecimalV2_7_0_ ,
propertymu1_4_.StringValue as StringVa2_8_0_
from [Video] this_
inner join [BaseEntity] this_1_ on this_.BaseEntity_id = this_1_.BaseId
inner join [PropertyMultTable] propertymu1_ on this_.BaseEntity_id = propertymu1_.BaseEntity_id
left outer join DateTimeValues propertymu1_1_ on propertymu1_.id = propertymu1_1_.PropertyMultTable_id
left outer join IntegerValues propertymu1_2_ on propertymu1_.id = propertymu1_2_.PropertyMultTable_id
left outer join DecimalValues propertymu1_3_ on propertymu1_.id = propertymu1_3_.PropertyMultTable_id
left outer join StringValues propertymu1_4_ on propertymu1_.id = propertymu1_4_.PropertyMultTable_id
where ( propertymu1_2_.IntegerValue >= 459144
and propertymu1_2_.IntegerValue <= 691982
)
but I want to get only the Entity, without the properties. So, I need SQL like this:
select this_.BaseEntity_id as BaseId0_1_ ,
this_1_.Label as Label0_1_ ,
this_1_.Description as Descript3_0_1_ ,
this_1_.CreatedDate as CreatedD4_0_1_ ,
this_.Width as Width2_1_ ,
this_.Height as Height2_1_ ,
this_.Duration as Duration2_1_
from [Video] this_
inner join [BaseEntity] this_1_ on this_.BaseEntity_id = this_1_.BaseId
inner join [PropertyMultTable] propertymu1_ on this_.BaseEntity_id = propertymu1_.BaseEntity_id
left outer join DateTimeValues propertymu1_1_ on propertymu1_.id = propertymu1_1_.PropertyMultTable_id
left outer join IntegerValues propertymu1_2_ on propertymu1_.id = propertymu1_2_.PropertyMultTable_id
left outer join DecimalValues propertymu1_3_ on propertymu1_.id = propertymu1_3_.PropertyMultTable_id
left outer join StringValues propertymu1_4_ on propertymu1_.id = propertymu1_4_.PropertyMultTable_id
where ( propertymu1_2_.IntegerValue >= 459144
and propertymu1_2_.IntegerValue <= 691982
)
or, even much better, like this:
select distinct this_.BaseEntity_id as BaseId0_1_ ,
this_1_.Label as Label0_1_ ,
this_1_.Description as Descript3_0_1_ ,
this_1_.CreatedDate as CreatedD4_0_1_ ,
this_.Width as Width2_1_ ,
this_.Height as Height2_1_ ,
this_.Duration as Duration2_1_
from [Video] this_
inner join [BaseEntity] this_1_ on this_.BaseEntity_id = this_1_.BaseId
inner join [PropertyMultTable] propertymu1_ on this_.BaseEntity_id = propertymu1_.BaseEntity_id
left outer join IntegerValues propertymu1_2_ on propertymu1_.id = propertymu1_2_.PropertyMultTable_id
where ( propertymu1_2_.IntegerValue >= 459144
and propertymu1_2_.IntegerValue <= 691982
)
Can I do this with Fluent NHibernate? Thanks for the responses.

here is how you can do it using HQL.
var hqlQuery=string.Format( "select v from Video as v inner join v.BaseEntity
as be inner join v.PropertyMultTable as pmt left outer join pmt.IntegerValues
as iv where be.BaseEntity_id=v.BaseId and be.BaseEntity_id=pmt.BaseEntity_id and
pmt.Id=iv.PropertyMultTable_id and iv.IntegerValue >={0} and iv.IntegerValue
<={1}", 459144,691982);
note here when inner join is done Im assuming the property names are the same as mentioned in the query above. they should be the exact same thing as mentione din your property or you will get an nhibernate exception.
If it doesnt work post the entire class diagram.
you can run this query as follows:
session.CreateQuery(hqlquery).List<Video>();

Maybe using Future():
var query =
_session.QueryOver<TEntity>()
.JoinQueryOver<PropertyMultTable>(p => p.Properties)
.Future()
.Where(propertyPredicate).List();

Related

Count Column in C# with join

I want to count my ReviewDetails.Review column but i got error:
Column 'AdvertiserMaster.AdvertiserID' is invalid in the select list
because it is not contained in either an aggregate function or the
GROUP BY clause.
Here Is My Query
SELECT DISTINCT
AdvertiserMaster.AdvertiserID, AdvertiserMaster.BusinessName , ISNULL(AdvertiserMaster.AverageRating, 0) AS AverageRating, AdvertiserMaster.ImageURL1, AdvertiserMaster.Address1,
AdvertiserMaster.CategoryID, AdvertiserMaster.Email, AdvertiserMaster.CountryID, AdvertiserMaster.StateID, AdvertiserMaster.CityID, AdvertiserMaster.PinCode, AdvertiserMaster.Mobile,
CategoryMaster.CategoryName, CountryMaster.CountryName, StateMaster.StateName, CityMaster.CityName,Count(ReviewDetails.Review) AS ReviewCount
FROM AdvertiserMaster INNER JOIN
BusinessCategoryDetails ON AdvertiserMaster.AdvertiserID = BusinessCategoryDetails.AdvertiserID INNER JOIN
ReviewDetails ON AdvertiserMaster.AdvertiserID = ReviewDetails.AdvertiserID LEFT OUTER JOIN
CategoryMaster ON AdvertiserMaster.CategoryID = CategoryMaster.CategoryID LEFT OUTER JOIN
CountryMaster ON AdvertiserMaster.CountryID = CountryMaster.CountryID LEFT OUTER JOIN
CityMaster ON AdvertiserMaster.CityID = CityMaster.CityID LEFT OUTER JOIN
StateMaster ON AdvertiserMaster.StateID = StateMaster.StateID LEFT OUTER JOIN
SubCategoryMaster ON BusinessCategoryDetails.SubCategoryID = SubCategoryMaster.SubCategoryID
WHERE (AdvertiserMaster.CategoryID = 8) AND (AdvertiserMaster.CityID = 16619) AND (AdvertiserMaster.IsActive = 1)
Since I am trying to get count by writing Count(ReviewDetails.Review)
But it is of no use.
here is my tables:ClassifiedBD Images
If you want to count something (or use other aggregate functions like sum), you need to define the level on which you count with group by clause, for example like this:
SELECT
AdvertiserMaster.AdvertiserID,
AdvertiserMaster.BusinessName,
ISNULL(AdvertiserMaster.AverageRating, 0) AS AverageRating,
AdvertiserMaster.ImageURL1,
AdvertiserMaster.Address1,
AdvertiserMaster.CategoryID,
AdvertiserMaster.Email,
AdvertiserMaster.CountryID,
AdvertiserMaster.StateID,
AdvertiserMaster.CityID,
AdvertiserMaster.PinCode,
AdvertiserMaster.Mobile,
CategoryMaster.CategoryName,
CountryMaster.CountryName,
StateMaster.StateName,
CityMaster.CityName,
COUNT(ReviewDetails.Review) AS ReviewCount
FROM AdvertiserMaster
INNER JOIN BusinessCategoryDetails
ON AdvertiserMaster.AdvertiserID = BusinessCategoryDetails.AdvertiserID
INNER JOIN ReviewDetails
ON AdvertiserMaster.AdvertiserID = ReviewDetails.AdvertiserID
LEFT OUTER JOIN CategoryMaster
ON AdvertiserMaster.CategoryID = CategoryMaster.CategoryID
LEFT OUTER JOIN CountryMaster
ON AdvertiserMaster.CountryID = CountryMaster.CountryID
LEFT OUTER JOIN CityMaster
ON AdvertiserMaster.CityID = CityMaster.CityID
LEFT OUTER JOIN StateMaster
ON AdvertiserMaster.StateID = StateMaster.StateID
LEFT OUTER JOIN SubCategoryMaster
ON BusinessCategoryDetails.SubCategoryID = SubCategoryMaster.SubCategoryID
WHERE (AdvertiserMaster.CategoryID = 8)
AND (AdvertiserMaster.CityID = 16619)
AND (AdvertiserMaster.IsActive = 1)
GROUP BY AdvertiserMaster.AdvertiserID,
AdvertiserMaster.BusinessName,
ISNULL(AdvertiserMaster.AverageRating, 0),
AdvertiserMaster.ImageURL1,
AdvertiserMaster.Address1,
AdvertiserMaster.CategoryID,
AdvertiserMaster.Email,
AdvertiserMaster.CountryID,
AdvertiserMaster.StateID,
AdvertiserMaster.CityID,
AdvertiserMaster.PinCode,
AdvertiserMaster.Mobile,
CategoryMaster.CategoryName,
CountryMaster.CountryName,
StateMaster.StateName,
CityMaster.CityName
You don't need distinct when you have group by.
You also might want to start using aliases for the tables and formatting / indenting your SQL properly

LINQ multiple joins with one left join

I am fairly new to LINQ and I am struggling to make a multiple JOIN.
So, this is how my database structure looks like:
Now, how should my query look like, if I have a particular Grade and I want to select
{Student.IndexNo, GradeValue.Value}, but if there is no grade value for a particular grade and particular user, null should be returned (Left join)?
The trick to get a LEFT join is to use the DefaultIfEmpty() method:
var otherValue = 5;
var deps = from tbl1 in Table1
join tbl2 in Table2
on tbl1.Key equals tbl2.Key into joinGroup
from j in joinGroup.DefaultIfEmpty()
where
j.SomeProperty == "Some Value"
&& tbl1.OtherProperty == otherValue
select j;
Deliberately posting this in 2015 for newbies looking for solution on google hits. I managed to hack and slash programming my way into solution.
var projDetails = from r in entities.ProjekRumah
join d in entities.StateDistricts on r.ProjekLocationID equals d.DistrictID
join j in entities.ProjekJenis on r.ProjekTypeID equals j.TypeID
join s in entities.ProjekStatus on r.ProjekStatusID equals s.StatusID
join approvalDetails in entities.ProjekApproval on r.ProjekID equals approvalDetails.ProjekID into approvalDetailsGroup
from a in approvalDetailsGroup.DefaultIfEmpty()
select new ProjectDetailsDTO()
{
ProjekID = r.ProjekID,
ProjekName = r.ProjekName,
ProjekDistrictName = d.DistrictName,
ProjekTypeName = j.TypeName,
ProjekStatusName = s.StatusName,
IsApprovalAccepted = a.IsApprovalAccepted ? "Approved" : "Draft",
ProjekApprovalRemarks = a.ApprovalRemarks
};
Produces following SQL code internally
{SELECT [Extent1].[ProjekID] AS [ProjekID]
,[Extent1].[ProjekName] AS [ProjekName]
,[Extent2].[DistrictName] AS [DistrictName]
,[Extent3].[TypeName] AS [TypeName]
,[Extent4].[StatusName] AS [StatusName]
,CASE
WHEN ([Extent5].[IsApprovalAccepted] = 1)
THEN N'Approved'
ELSE N'Draft'
END AS [C1]
,[Extent5].[ApprovalRemarks] AS [ApprovalRemarks]
FROM [dbo].[ProjekRumah] AS [Extent1]
INNER JOIN [dbo].[StateDistricts] AS [Extent2] ON [Extent1].[ProjekLocationID] = [Extent2].[DistrictID]
INNER JOIN [dbo].[ProjekJenis] AS [Extent3] ON [Extent1].[ProjekTypeID] = [Extent3].[TypeID]
INNER JOIN [dbo].[ProjekStatus] AS [Extent4] ON [Extent1].[ProjekStatusID] = [Extent4].[StatusID]
LEFT JOIN [dbo].[ProjekApproval] AS [Extent5] ON [Extent1].[ProjekID] = [Extent5].[ProjekID]
}

SQL to Linq: RIGHT JOIN in LINQ

anybody can help me to convert some sql query whit right join like this to linq ?
SELECT dbo.FinnTrans.SanadID, dbo.FinnTrans.Date, dbo.FinnAccount.ID AS AccID,
dbo.FinnAccount.FullId, dbo.FinnAccount.Name, SUM(dbo.FinnTrans.Debit) AS TotalDebit,
SUM(dbo.FinnTrans.Credit) AS TotalCredit
FROM dbo.FinnAccount AS FinnAccount_1 LEFT OUTER JOIN
dbo.FinnAccount ON FinnAccount_1.ParentId = dbo.FinnAccount.ID RIGHT OUTER JOIN
dbo.FinnTrans LEFT OUTER JOIN
dbo.FinnAccount AS FinnAccount_2 ON dbo.FinnTrans.AccID = FinnAccount_2.ID ON
FinnAccount_1.ID = FinnAccount_2.ParentId
WHERE (dbo.FinnTrans.FPID = 7) AND (FinnAccount_2.AccLevel = 3)
GROUP BY dbo.FinnTrans.SanadID, dbo.FinnTrans.Date, dbo.FinnAccount.ID,
dbo.FinnAccount.Name, dbo.FinnAccount.FullId
HAVING (dbo.FinnTrans.SanadID = 1)
You can look here: http://www.hookedonlinq.com/OuterJoinSample.ashx as an example of the left outer join. And you can always swap tables to get either left or right
I've taken the liberty of beatifying your TSQL a little.
The last two join conditions appear malformed to me so this TSQL can not be parsed.
SELECT
[t].SanadID
, [t].Date
, [a].ID [AccID]
, [a].FullId
, [a].Name
, SUM([t].Debit) [TotalDebit]
, SUM([t].Credit) [TotalCredit]
FROM
dbo.FinnAccount [a1]
LEFT OUTER JOIN
dbo.FinnAccount [a]
ON [a1].ParentId = [a].ID
RIGHT OUTER JOIN
dbo.FinnTrans [t]
LEFT OUTER JOIN
dbo.FinnAccount [a2]
ON [a].AccID = [a2].ID
ON [a1].ID = [a2].ParentId
WHERE
[t].FPID = 7
AND
[a2].AccLevel = 3
GROUP BY
[t].SanadID
, [t].Date
, [a].ID
, [a].Name
, [a].FullId
HAVING
[t].SanadID = 1

How to use the results of the previous query in the next query?

As a result of this query I have a table:
select i.id, o.[name] from Item i
LEFT OUTER JOIN sys.objects o on o.[name]='I' + cast(i.id as nvarchar(20))
where o.name is not null
Now I need to use the result of this table in the next query:
select PriceListItem.ProductExternalId, #id.Id, #id.FriendlyName, #id.BriefWiki,
[PriceListItem].[ProductExternalDesc]
from [#id]
inner join [Product] on Product.ItemId = #name and Product.InstanceId = #id.ID
inner join [PriceListItem] on Product.ID = PriceListItem.ProductId
instead of '#id' I should use data from the table with name= id, and instead of '#name' I should use data from the table with name= name
Standard SQL way, works in most RDBMS
select PriceListItem.ProductExternalId, #id.Id, #id.FriendlyName, #id.BriefWiki,
[PriceListItem].[ProductExternalDesc]
from
(
select i.id, o.[name] from Item i
LEFT OUTER JOIN sys.objects o on o.[name]='I' + cast(i.id as nvarchar(20))
where o.name is not null
)
X
inner JOIN
[#id] ON X.id = #id.id --change here as needed
inner join [Product] on Product.ItemId = #name and Product.InstanceId = #id.ID
inner join [PriceListItem] on Product.ID = PriceListItem.ProductId*
Since you're on SQL 2K8 you can use a CTE:
-- You may need a ; before WITH as in ;WITH
WITH FirstQuery AS (
select i.id, o.[name] from Item i
LEFT OUTER JOIN sys.objects o on o.[name]='I' + cast(i.id as nvarchar(20))
where o.name is not null
)
select PriceListItem.ProductExternalId,
FQ.Id,
-- Neither of these are in your FirstQuery so you can not use them
-- #id.FriendlyName, #id.BriefWiki,
[PriceListItem].[ProductExternalDesc]
from FirstQuery FQ
inner join [Product] on Product.ItemId = FQ.name
and Product.InstanceId = FQ.ID
inner join [PriceListItem] on Product.ID = PriceListItem.ProductId;
From the queries alone it's tough to tell how you plan to JOIN them, but this will allow you to make use of the first query in the subsequent one.
Looks like you have some syntax errors in your second query - #id.id?
select i.id, o.[name] from Item i
into #temp_table
LEFT OUTER JOIN sys.objects o on o.[name]='I' + cast(i.id as nvarchar(20))
where o.name is not null
Now you can use #temp_table as you want :)

nHibernate complex join

I have a need to perform a complex left join on a table and am unsure how to write the code using a criteria query. Currently I have:
public IList<RezolutionConfig> GetSearchConfigByManagerCategoryProduct(int ManagerId, int ProductTypeId, int ConfigCategoryId)
{
ICriteria criteria = Session.GetISession().CreateCriteria(typeof(RezolutionConfig))
.CreateAlias("RezolutionConfigCategory", "rcc")
.Add(Expression.Eq("rcc.id", ConfigCategoryId))
.CreateAlias("RezolutionProductType","rpt")
.Add(Expression.Eq("rpt.id", ProductTypeId))
.CreateAlias("RezolutionManagerConfigs", "rmc", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.CreateAlias("rmc.Manager", "m", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.Add(Expression.Eq("m.id", ManagerId));
return criteria.List<RezolutionConfig>();
}
which produces:
SELECT *
FROM [dbo].[RezolutionConfig] this_
inner join [dbo].[RezolutionConfigCategory] rcc1_ on this_.[RezolutionConfigCategoryId]=rcc1_.[RezolutionConfigCategoryId]
inner join [dbo].[RezolutionProductType] rpt2_ on this_.[RezolutionProductTypeId]=rpt2_.[RezolutionProductTypeId]
left outer join [dbo].[RezolutionManagerConfig] rmc3_ on this_.[RezolutionConfigID]=rmc3_.[RezolutionConfigID]
left outer join [dbo].[Manager] m4_ on rmc3_.[ManagerID]=m4_.[ManagerID] WHERE rcc1_.[RezolutionConfigCategoryId] = 1
and rpt2_.[RezolutionProductTypeId] = 1
and m4_.[ManagerID] = 9135
What I need to produce is
SELECT *
FROM [dbo].[RezolutionConfig] this_
inner join [dbo].[RezolutionConfigCategory] rcc1_ on this_.[RezolutionConfigCategoryId]=rcc1_.[RezolutionConfigCategoryId]
inner join [dbo].[RezolutionProductType] rpt2_ on this_.[RezolutionProductTypeId]=rpt2_.[RezolutionProductTypeId]
left outer join [dbo].[RezolutionManagerConfig] rmc3_ on this_.[RezolutionConfigID]=rmc3_.[RezolutionConfigID]
left outer join [dbo].[Manager] m4_ on rmc3_.[ManagerID]=m4_.[ManagerID] and m4_.[ManagerID] = 9135
WHERE rcc1_.[RezolutionConfigCategoryId] = 1
and rpt2_.[RezolutionProductTypeId] = 1
NHibernate doesn't support adding a constraint to a join as you would like: left outer join [dbo].[Manager] m4_ on rmc3_.[ManagerID]=m4_.[ManagerID] and m4_.[ManagerID] = 9135. I think your best approach will be to write the query in HQL and use a subquery to constrain Manager.

Categories

Resources