How to get the latest/last record with a group by clause with NHibernate Linq provider - nhibernate

I have used too much time (days) on this and I really hope someone can help me out.
I found a good article on describing my problem in a generic way so let's stick to it.
I am trying to build this query but NHibernate fails to build the correct sql and returns a sql query exception.
Column vSagsAendring.Id is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. It could not execute the following query:
select
viewsagsae0_.Id as Id155_,
viewsagsae0_.SagId as SagId155_,
viewsagsae0_.JournalNr as JournalNr155_,
viewsagsae0_.LbfNr as LbfNr155_,
viewsagsae0_.OrgNr as OrgNr155_,
viewsagsae0_.OrgNavn as OrgNavn155_,
viewsagsae0_.AfdNavn as AfdNavn155_,
viewsagsae0_.SagsType as SagsType155_,
viewsagsae0_.Status as Status155_,
viewsagsae0_.SagsbehandlerInit as Sagsbeh10_155_,
viewsagsae0_.Dato as Dato155_,
viewsagsae0_.JournalAktionType as Journal12_155_,
viewsagsae0_.Beskrivelse as Beskriv13_155_,
viewsagsae0_.Ekstern as Ekstern155_
from vSagsAendring viewsagsae0_
group by viewsagsae0_.SagId
var query = from p in _session.Query<ViewSagsAendring>()
group p by p.SagId
into grp
select grp.OrderByDescending(g => g.Dato).First();
This is another version also took from the article:
var query = from p in _session.Query<ViewSagsAendring>()
group p by p.SagId
into grp
let maxDato = grp.Max(g => g.Dato)
from p in grp
where p.Dato == maxDato
select p;

It's have been a long journey, but now it's over. I hope that I can help someone else in the same situation by answering my own question.
var aendring = from sagsAendring in _session.Query<ViewSagsAendring>()
where sagsAendring.Dato ==
(
from innersagsAendring in _session.Query<ViewSagsAendring>()
where innersagsAendring.SagId == sagsAendring.SagId
select innersagsAendring.Dato
).Max()
select sagsAendring;
var result = aendring.ToList();
And because you can chain linq statements you can build a linq filter like this
if(Filters.VisInterneAendringer == false)
query = query.Where(x => x.Ekstern == true);
if (Filters.VisKunNyesteAendringer)
{
query = query.Where(sagsAendring => sagsAendring.Dato ==
(
from innerSagsAendring in Session.Query<ViewSagsAendring>() where innerSagsAendring.SagId == sagsAendring.SagId
select innerSagsAendring.Dato
).Max());
}
return query;

Your queries seem legit for LINQ in EntityFramework.
I'm not sure about hibernate, you might try to use QueryOver API instead of Query
http://nhibernate.info/blog/2009/12/17/queryover-in-nh-3-0.html

Related

Entity Framework, why is this sql being generated?

When I look at the SQL query generated by EF I see
SELECT [extent1].ID as ID,
[extent1].Name as Name
From(
Select myview.ID as ID,
myview.Name as Name
From myview) AS [extent1]
Where([Extent1].ID = #p_linq_0)
Why is the outside select happening on the inside select? I've got a very large table that I can get a record from easily with the outside query but the whole query combined times out.
My Linq query
var result = from i in invitationEntity.Invitations
.Where(a=>a.id == inviationId)
select i;
I am using SQL 2012 & EF5 & Linq.
Is there a way to "force" the simpler query?
Because you are calling "SELECT" once again at the end along with LINQ method.
var result = from i in invitationEntity.Invitations
.Where(a=>a.id == inviationId)
select i;
The last line select i, is useless, but EF is not aware of it whether it has anything useful or not, you can simply avoid it.
var result = invitationEntity.Invitations
.Where(a=>a.id == inviationId);
You can still enumerate result and get everything.
Ok sorry, I forgot to add, you don't have to use "from", you can simply use .Where(expression )
And if you want to use LINQ keywords, then you can use it this way,
var result = from i in invitationEntity.Invitations
where i.id == invitationId
select i;
You cannot mix LINQ keywords and LINQ extension methods.
i would say that
var result = from i in invitationEntity.Invitations
.Where(a=>a.id == inviationId)
select i;
this
a=>a.id == inviationId
from a=> generate
Select myview.ID as ID,
myview.Name as Name
From myview
so a is [extent1]
you should use a "standard" where clause
from i in invitationEntity.Invitations
where i.id == inviationId
select i;

Convert Sql query with Group by and Having clause to Linq To Sql query in C#

I need help to convert following ql query to Linq to Sql query.
select Name, Address
from Entity
group by Name, Address
having count(distinct LinkedTo) = 1
Idea is to find all unique Name, Address pairs who only have 1 distinct LinkedTo value. Remember that there are other columns in the table as well.
I would try something like this:
Entity.GroupBy(e => new { e.Name, e.Address})
.Where(g => g.Select(e => e.LinkedTo).Distinct().Count() == 1)
.Select(g => g.Key);
You should put a breakpoint after that line and check the SQL that is generated to find what is really going to the database.
You could use:
from ent in Entities
group ent by new { ent.Name, ent.Address } into grouped
where grouped.Select(g => g.LinkedTo).Distinct().Count() == 1
select new { grouped.Key.Name, grouped.Key.Address }
The generated SQL does not use a having clause. I'm not sure LINQ can generate that.

Converting SQL script to LINQ with IN clause

I am trying to work out how to covert the script below from SQL in to LINQ. Any help would be welcome.
SELECT *
FROM
[tableName]
WHERE
[MyDate] IN
(SELECT
MAX([MyDate])
FROM
[tableName]
GROUP BY
[MyID])
I can't find an equivalent for the "IN" clause section. There are existing questions on this forum but none that cover selecting a DateTime.
Thanks in advance.
You can use the ".Contains(..)" function:
e.g.
var itemQuery = from cartItems in db.SalesOrderDetails
where cartItems.SalesOrderID == 75144
select cartItems.ProductID;
var myProducts = from p in db.Products
where itemQuery.Contains(p.ProductID)
select p;
Although it looks like 2 round trips, as the LINQ only constructs the query when the IEnumerable is tripped, you should get reasonable performance.
I think Any() is what you are looking for:
var result = tableName.Where(x =>
(from t in tableName
group t by t.MyID into g
where g.Max(y => y.MyDate) == x.MyDate
select 1).Any())

Linq to sql constantly returns null

I have the following SQL query:
SELECT DISTINCT
Participant.BackgroundTrainingID,
Location.TrainingSite
FROM Registration, ProgramLocation, Participant, Program, Location
WHERE ProgramLocation.LocationID = Location.LocationID
AND ProgramLocation.ProgramID=Registration.ProgramID
AND Registration.ParticipantID=Participant.ParticipantId
I wrote the following LINQ to SQL to match the query above:
var trainingsiteinfo = (from c in db.ProgramLocations
from n in db.Registrations
from l in db.Participants
from h in db.Locations
where c.LocationID == h.LocationID
&& c.ProgramID == n.ProgramID
&& n.ParticipantID == l.ParticipantId
select new {
h.TrainingSite,
l.BackgroundTrainingID }).Distinct();
The SQL query works fine but LINQ constantly returns null.
I use Linqer http://www.sqltolinq.com/ when i get out of ideas :-) Aswell it speeds up conversion jobs.
Make sure your db context isn't going out of scope before you have bound your results. You can test this by adding .ToList() after your .Distinct() to force eager loading of the results.
Your linq code has an unclosed } bracket in the select statement

Having problems converting conditional where clause in LINQ back over to SQL

I've got myself in a bit of a pickle!
I've done a snazzy LINQ statement that does the job in my web app, but now I'd like to use this in a stored procedure:
var r = (from p in getautocompleteweightsproducts.tblWeights
where p.MemberId == memberid &&
p.LocationId == locationid
select p);
if (level != "0")
r = r.Where(p => p.MaterialLevel == level);
if (column == "UnitUserField1")
r = r.Where(p => p.UnitUserField1 == acitem);
if (column == "UnitUserField2")
r = r.Where(p => p.UnitUserField2 == acitem);
return r.OrderBy(p => p.LevelNo).ToList();
However, I can't for the life of me get the conditional where clause to work!!
If someone can point me in the right direction, I'd be most grateful.
Kind regards
Maybe something like this?
SELECT *
FROM dbo.weights
WHERE member_id = #memberid
AND location_id = #locationid
AND material_level = CASE WHEN #level = '0' THEN material_level
ELSE #level END
AND #acitem = CASE #column WHEN 'UnitUserField1' THEN unit_user_field_1
WHEN 'UnitUserField2' THEN unit_user_field_2
ELSE #acitem END
ORDER BY level_no
Have you tried LinqPAD, I'm pretty sure last time I played with that you could enter "LINQ to SQL" code and see the resulting SQL that produced. Failing that, place a SQL trace/profiler on your code running the LinqTOSQL and find the query being executed in the trace.
LukeH's answer will give you the correct rows, but there is something lost when you try to replace a query-generating-machine with a single query. There are parts of that query that are opaque to the optimizer.
If you need the original queries as-would-have-been-generated-by-linq, there are two options.
Generate every possible query and control which one runs by IF ELSE.
Use Dynamic sql to construct each query (although this trades away many of the benefits of using a stored procedure).
If you do decide to use dynamic sql, you should be aware of the curse and blessings of it.