I can't seem to find any solid answer to the problem, I'm hoping someone will be able to help me here.
Sample query:
select * from A a inner join B b on a.Id = b.Id Or a.Date = b.Date
Basically I want to know if it's possible to implement the second part of the join condition using criteria, and if it is possible, how to go about it. If anyone can please let me know, that will be great! Thanks a bunch!
It might be, but that query is more clear written in HQL:
select a from A a, B b where a.Id = b.Id or a.Date = b.Date
As you can see, it's almost the same as the SQL.
Unfortunately you cannot define ANSI syntax joins with NHibernate.
With NH2 and onward you can define them on HQL using a WITH clause and i say so because if you use Diego's solution you will have to set up a ISNULL OR pattern in your queries if you want to perform multiple joins.
to add conditions, use Expressions. For the OR disjunction, its less complex if you use Expresion.In
session.CreateCriteria(typeof(A), "a").CreateCriteria("B", "b", NHibernate.SqlCommand.JoinType.FullJoin)
.Add(Expression.Eq("a.Date", a.Date))
.Add(Expression.Eq("b.Date", b.Date))
Related
I've periodically seen it written that joins are unnecessary in LINQ to SQL. Most recently, I saw this statement in one of Joseph Albahari's LINQPad samples (Chapter 9 - LINQ Operators > Filtering > Joining > Simple Join).
The comment says:
// Note: before delving into this section, make sure you've read the preceding two
// sections: Select and SelectMany. The Join operators are actually unnecessary
// in LINQ to SQL, and the equivalent of SQL inner and outer joins is most easily
// achieved in LINQ to SQL using Select/SelectMany and subqueries!
I've gone through the Select and SelectMany sections in LINQPad and I definitely want to be doing this the easy way, but my attempts to completely remove joins (and get the same results) have failed.
Anyway, below is the 100% working query I'm trying this out on (full schema pictured below).
(from workOrder in dbContext.WorkOrders.Where(wo => wo.WoId == workOrderLine.WoId)
join projectsBillingSchedule in dbContext.ProjectsBillingSchedules
on workOrder.ProjectId equals projectsBillingSchedule.ProjectId
join partyPricing in dbContext.PARTY_PRICING.Where(pp => pp.END_DATE_ACTIVE == endDateActive)
on projectsBillingSchedule.BillingSchId equals partyPricing.BILLING_SCH_ID
join measuresPartyRetrofitCode in dbContext.MeasuresPartyRetrofitCodes
on partyPricing.PARTY_RETROFIT_CODE_ID equals measuresPartyRetrofitCode.PartyRetrofitCodeId
join measure in dbContext.Measures on measuresPartyRetrofitCode.ConvId equals measure.ConvId
select measure).FirstOrDefault(m => m.ConvId == workOrderLine.ConvId)
Please note, certain entities are omitted from the code because they are not strictly necessary for the query to run properly. Aside from that, you can see the joins are done in order of the relationships in the schema image, i.e., from WORK_ORDERS to MEASURES (start by moving away from WORK_ORDER_LINES):
I have tried some using navigation properties, but I run into 2 problems:
The SQL outputs in multiple statements (N+1 problem?), and
I can't seem to get it all in one statement.
So, back to my question - using the example above (or something else with a lot of joins), how are join operators unnecessary in LINQ to SQL?
UPDATE
Ok, I think I've figured out one solution, but this actually requires more lines of code to achieve the same result.
Since that is the case, I'm not sure why it is worth exclaiming that join operators are unnecessary. I'll leave this question open for a while to see if someone wants to make a compelling case against joins.
(from workOrder in dbContext.WorkOrders.Where(wo => wo.WoId == workOrderLine.WoId)
from projectsBillingSchedule in dbContext.ProjectsBillingSchedules
where workOrder.ProjectId == projectsBillingSchedule.ProjectId
from partyPricing in dbContext.PARTY_PRICING.Where(pp => pp.END_DATE_ACTIVE == endDateActive)
where projectsBillingSchedule.BillingSchId == partyPricing.BILLING_SCH_ID
from measuresPartyRetrofitCode in dbContext.MeasuresPartyRetrofitCodes
where partyPricing.PARTY_RETROFIT_CODE_ID == measuresPartyRetrofitCode.PartyRetrofitCodeId
from measure in dbContext.Measures
where measure.ConvId == measuresPartyRetrofitCode.ConvId
select measure).FirstOrDefault(m => m.ConvId == workOrderLine.ConvId)
I have three tables (Table A, B and C).
I would like to do the following:
Left Join A with B and Left join A with C.
Now I have used CreateCriteria, to do the joins using jointype which worked upto a certain point but it's throwing Query exception. It seems this is because it's seems to attempt to left join B with C rather than A and C.
Code:
currencies = session.CreateCriteria(typeof(Currency), "TableA")
.CreateCriteria("FXRates", "TableB",
JoinType.LeftOuterJoin,
Expression.Eq("fxrate.RateDate",date))
.CreateCriteria("FundingRates", "TableC",
JoinType.LeftOuterJoin,
Expression.Eq("fundingrate.RateDate", date))
.Add(Restrictions.IsNotNull("currency.code"))
.List<Currency>();
Apologies in advanced if I have missed out anything or not provided enough detail, let me know if you need more...
You can use NHibernate "QueryOver" to do it:
session.QueryOver<Item_A>()
.Left.JoinQueryOver(item_A => item_A.Item_B)
.Left.JoinQueryOver(item_A => item_A.Item_C)
.TransformUsing(Transformers.DistinctRootEntity)
.List();
Currently I'm running some code and got some question about this. Below are the code listings of two LINQ to Entites queries.
Code listing A:
IQueryable list =
from tableProject in db.Project
select new {StaffInCharge = (
from tableStaff in db.Staff
where tableStaff.StaffId == tableProject.StaffInChargeId
select tableStaff.StaffName)};
Code listing B:
IQueryable list =
from tableProjectin db.Project
join tableStaff in db.Staff
on tableProject.StaffInChargeId
equal tableStaff.StaffId
select new {StaffInCharge = tableStaff.StaffName};
What I want to figure out is which one will be better and faster if I have to select many column from many others table.
Thanks.
this is the comment from #Tim Schmelter
"The article(actually my SO-Question) relates to LINQ-To-DataSet what is based on LINQ-To-Objects. Linq to SQL or Linq to Entities might be optimized by the DBMS in that way that a where clause has the same performance as a join."
and the link is
Why is LINQ JOIN so much faster than linking with WHERE?
i think it is very useful.
I simply can not get this to work out at all, so any expert help would be very much appreciated.
I'm trying (as the subject suggests) to join 2 datatables on Zip Code, but return a table which grouped this by State and has a SUM() of sales.
Here's the latest version of my troubles:
var results =(
from a in dtList.AsEnumerable()
join b in dtListCoded.AsEnumerable()
on a.Field<string>("ZIP") equals b.Field<string>("zip")
group a by {a.Field<string>("StateCode")} into g
select new {
StateCode = a.Field<string>("StateCode"),
SumSales = b.Sum(b => b.Field<double>("SUMSales"))
});
I can join the 2 tables but its getting the result i need that seems to be the tricky bit. If need be I will just have to do 2 queries, but that just seems a bit backward.
Thanks in advance.
Two queries wouldn't be any slower (they should be brought together into a single SQL query upon execution), and would be a lot more readable, transparent during debugging and reusable. I'd recommend breaking it down.
I have a question on criteria:
How can i use a Criteria (or similar) that filters and/or do whatever with another criteria?
Something like:
select clients.* from
(select * from clients) as clients
The real problem is something else, but achieving this behaviour would be terrific...
(btw, both java and .net are welcome to help)
thanks
It can't be done, AFAIK. The tutorial about HQL says:
Note that HQL subqueries can occur only in the select or where clauses.
I can't find same statement about Criteria, but in API the only way to create criteria is to give mapped type. There is support for subqueries but only in where clause. Here is javadoc.
Your FROM clause needs to be a mapped object. You could do a subselect inside the WHERE clause... something like:
select c from clients c where c.id in (select c2.id from clients c2)
It would help if you could give a better example. The example you gave can be reduced down to the following HQL:
"from clients"
...which isn't terribly useful.
You could try adding a NHibernate.Criterion.InExpression to your criteria.
Found an example on this blog:
http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/08/26/parameter-lists-in-nhibernate.aspx
i'm not sure i understand your question correctly, but if you want to do a select on a list of objects, you can use the subqueries with DetachedCriteria. I use it all the time, especially for paging objects while creating a left outer join, which could lead me to incorrect number of entities.
Imagine you've got users who buy products, with a relationship many-many:
Dim dc As DetachedCriteria = DetachedCriteria.For(GetType(User)).SetFirstResult(pageNumber * itemsPerPage).SetMaxResults(itemsPerPage)
Session.CreateCriteria(GetType(user)).Add(Subqueries.PropertyIn("Id", dc)).CreateAlias("ProductsBought", "pb", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
Thom's right, perhaps you should be more precise...