How can I create nhibernate query, that should look like the below sql query
select * from A
left outer join B on A.ID = B.ID
left outer join C on B.ProdID = C.ProdID
Unfortunately, I can't use the named query.
And what the mapping of A should look like?
Thanks.
Map B as a many-to-one property of A. The B to C relation doesn't seem to be a normal foreign key and can't be mapped as a property. So it can't be left outer joined.
HQL, C can't be left outer joined:
select *
from A a
left join a.B b,
C c
where
c.Description = b.Description
Related
I'm trying to do the following query in linq-to-sql (joining 3 different tables):
select * from tbl_round r
inner join tbl_election e on r.fk_election_id = e.election_id
inner join tbl_meeting m on m.meeting_id = e.fk_meeting_id
Here is what I have so far but not correct:
from round in db.tbl_rounds
join meeting in db.tbl_meetings on election.fk_meeting_id equals meeting.meeting_id
join election in db.tbl_elections on round.fk_election_id equals election.election_id
select round;
The error I'm getting is that the name 'election' does not exist in the current context.
You will have to re-order the join statement probably like
from round in db.tbl_rounds
join election in db.tbl_elections on round.fk_election_id equals election.election_id
join meeting in db.tbl_meetings on election.fk_meeting_id equals meeting.meeting_id
select round;
Because you have "election" used before it is declared.
from round in db.tbl_rounds
join meeting in db.tbl_meetings on -->election<--.fk_meeting_id equals meeting.meeting_id
join -->election<-- in db.tbl_elections on round.fk_election_id equals election.election_id
select round;
In this case, you will need to change order in your query.
Query should look like this:
from round in db.tbl_rounds
join election in db.tbl_elections on round.fk_election_id equals election.election_id
join meeting in db.tbl_meetings on election.fk_meeting_id equals meeting.meeting_id
select round;
So I have a SQL query that I would like to convert to LINQ.
Here is said query:
SELECT *
FROM DatabaseA.SchemaA.TableA ta
LEFT OUTER JOIN DatabaseA.SchemaA.TableB tb
ON tb.ShipId = ta.ShipId
INNER JOIN DatabaseA.SchemaA.TableC tc
ON tc.PostageId= tb.PostageId
WHERE tc.PostageCode = 'Package'
AND ta.MailId = 'Specification'
The problem I am struggling with is I cannot seem to figure out how to do a left join in LINQ before an inner join, since doing a left join in LINQ is not as clear to me at least.
I have found numerous examples of a LINQ inner join and then a left join, but not left join and then inner join.
If it helps, here is the LINQ query I have been playing around with:
var query = from m in tableA
join s in tableB on m.ShipId equals s.ShipId into queryDetails
from qd in queryDetails.DefaultIfEmpty()
join p in tableC on qd.PostageId equals p.PostageId
where m.MailId == "Specification" && p.PostageCode == "Package"
select m.MailId;
I have tried this a few different ways but I keep getting an "Object reference not set to an instance of an object" error on qd.PostageId.
LINQ is very new to me and I love learning it, so any help on this would be much appreciated. Thanks!
From my SQL conversion recipe:
JOIN conditions that aren't all equality tests with AND must be handled using where clauses outside the join, or with cross product (from ... from ...) and then where
JOIN conditions that are multiple ANDed equality tests between the two tables should be translated into anonymous objects
LEFT JOIN is simulated by using into joinvariable and doing another from from the joinvariable followed by .DefaultIfEmpty().
The order of JOIN clauses doesn't change how you translate them:
var ans = from ta in TableA
join tb in TableB on ta.ShipId equals tb.ShipId into tbj
from tb in tbj.DefaultIfEmpty()
join tc in TableC on tb.PostageId equals tc.PostageId
where tc.PostageCode == "Package" && ta.MailId == "Specification"
select new { ta, tb, tc };
However, because the LEFT JOIN is executed before the INNER JOIN and then the NULL PostageIds in TableB for unmatched rows will never match any row in TableC, it becomes equivalent to an INNER JOIN as well, which translates as:
var ans2 = from ta in tableA
join tb in tableB on ta.ShipId equals tb.ShipId
join tc in tableC on tb.PostageId equals tc.PostageId
where tc.PostageCode == "Package" && ta.MailId == "Specification"
select new { ta, tb, tc };
Use:
var query = from m in tableA
join s in tableB on m.ShipId equals s.ShipId
join p in tableC on s.PostageId equals p.PostageId
where m.MailId == "Specification" && p.PostageCode == "Package"
select m.MailId;
Your query uses a LEFT OUTER JOIN but it doesn't need it.
It will, in practice, function as an INNER JOIN due to your tc.PostageCode = 'Package' clause. If you compare to a column value in a table in a WHERE clause (and there are no OR clauses and you aren't comparing to NULL) then effectively all joins to get to that table will be treated as INNER).
That clause will never be true if TableB is null (which is why you use LEFT OUTER JOIN vs INNER JOIN) - so you should just use an INNER JOIN to make the problem simpler.
I have this MySQL query which does what I want. But I don't know how to translate this query to linq, the part of the UNION is what confuses me.
The MYSQL query:
SELECT * FROM conta.subrecurso as a
left join conta.recurso as b on a.idRecurso=b.idRecurso
left join conta.eventorecurso as c on b.idRecurso=c.idRecurso
left join conta.recursocliente as d on a.idSubrecurso=d.idSubrecurso
left join conta.eventocliente as e on d.idVenta=e.idVenta
where c.idEvento=47 And e.idVenta =784
UNION
SELECT * FROM conta.subrecurso as a
left join conta.recurso as b on a.idRecurso=b.idRecurso
left join conta.eventorecurso as c on b.idRecurso=c.idRecurso
left join conta.recursocliente as d on a.idSubrecurso=d.idSubrecurso
left join conta.eventocliente as e on d.idVenta=e.idVenta
WHERE c.idEvento=47 and e.idVenta is null ;
There's a similar question.
In the answer the solved it in that way:
(sqlstatement1).Union(sqlstatement2);
Let's say I have this query in SQL:
SELECT
....
FROM
TableA a
JOIN TableB b on a.Id = b.Id
I've got that working just fine as a linq query:
var results = (from a in db.TableA
join b in db.TableB on a.Id equals b.Id
select new MyObject {...}).ToList();
But now I want to add a left join to the mix as well. In SQL:
SELECT
....
FROM
TableA a
JOIN TableB b on a.Id = b.Id
LEFT JOIN TableC c on a.Id2 = c.Id2
I'm not sure how to handle this in the linq query.
SQL's LEFT JOIN concept is a pretty clunky abstraction when you think about what you're really trying to do. You really want, for every TableA entry, to have a list of TableC items associated with it, right?
LINQ uses a much simpler (IMO) way to represent this abstraction, because it has the concept of nested, hierarchical objects. The provider will generate a LEFT JOIN, but it'll also build the result into an object structure that's easy to work with.
var results = (from a in db.TableA
join b in db.TableB on a.Id equals b.Id
select new MyObject {
...
TableCEntries =
from c in db.TableC
where c.Id == a.Id
select c // or select specific values from c
}).ToList();
If you really want your results flattened out the way they would be with a left outer join, you could do this:
var results = (from a in db.TableA
join b in db.TableB on a.Id equals b.Id
from c in db.TableC
where c.Id == a.Id
select new MyObject {
...
}).ToList();
... but you wouldn't get any entries for TableA where there are no entries present for TableC. For that behavior you'd have to do ugly stuff with group by/DefaultIfEmpty as shown in Ivan Stoev's link.
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.