NHibernate SQLquery for paging to HQL / ICriteria - c#

I'm making a query that sorts and returns X rows based on row_number()
I'm using NHibernate with MSSQL and im trying to get paging working using CreateSQLQuery and i have this query:
select s.*
from(
select distinct release.[stop], survey.SurveyId, survey.Created, survey.CopyOfId, survey.DesignTemplateId, survey.UserId, survey.Template, [Row] = Row_Number() over (order by survey.[SurveyId])
from Survey as survey
inner join Release as release on release.SurveyId = survey.SurveyId
group by survey.SurveyId
, survey.Created
, survey.CopyOfId
, survey.DesignTemplateId
, survey.UserId
, survey.Template
, release.[stop]
) as s
where s.[Row] >= 0 and s.[Row] <= 20
order by s.[stop]
does anyone know how to get this working using HQL or ICriteria (even better) instead of plain SQL? The reason for this is that I want a query that is compatible with both SQLite and MS SQL Server 2005, so that i can use .SetMaxResult() og .SetFirstResult()
Thanks in advance!

Try to avoid using plain SQL in nHibernate.
On Criteria object, use SetFirstResult() and SetMaxResult() for your paging.
Pages of 10 records ? First page is criteria.SetFirstResult(0).SetMaxResult(10) and third page is criteria.SetFirstResult(20).SetMaxResult(10)
Always use the correct dialect. For exemple SQL Server 2008 has more paging features than SQL Server 2005.

Here's an excellent article to do what you want
http://www.tobinharris.com/past/2008/10/20/almost-iqueryable-with-nhibernate-hql/

Related

Select N Row with DB2 in Visual Studio

I want to get the first 95 data from DB2 in Visual Studio. I'm using table adapter and I have this query,
SELECT * FROM ASEINDTA.TRX_BWS WHERE (DKLDATE
= '2019-10-31') Fetch First 95 Rows Only
or this
SELECT * FROM ASEINDTA.TRX_BWS WHERE (DKLDATE
= '2019-10-31') ORDER BY Col[ 1 ]...Col[ n ]
Fetch First 95 Rows Only
But when I click Query Builder, this error appears.
But when I tried it in DBVisualizer, it works. How do I get that data? A help would be appreciate. Thanks
One approach would work on DB2 and most other databases would be to use ROW_NUMBER with a subquery:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY some_col) rn
FROM ASEINDTA.TRX_BWS
WHERE DKLDATE = '2019-10-31'
)
SELECT *
FROM cte
WHERE rn <= 95;
Or, the inlined version that does not use CTE:
SELECT *
FROM
(
SELECT *, ROW_NUMBER() OVER (ORDER BY some_col) rn
FROM ASEINDTA.TRX_BWS
WHERE DKLDATE = '2019-10-31'
) t
WHERE rn <= 95;
Remove the parentheses of the where clause:
SELECT * FROM ASEINDTA.TRX_BWS WHERE DKLDATE = '2019-10-31' Fetch First 95 Rows Only
It seems the issue is not on db2-server it-self, but from the tool you are using to execute the queries. You said, if you run the same in 'DBVisualizer' it works properly.
Looking at db2 documentation for this error: sqlcode -104 sqlstate 42601
it seems this error is returned by SYSPROC.ADMIN_CMD stored procedure.
This procedure is designed to run db2 administration commands in the target database, remotely. It was not designed to run queries... so, the parser for this proc is just a sub-set of db2 parser, just for specific admin commands.
So it's complaining about the FETCH token from your query.
It seems that the tool you are using 'I'm using table adapter' (no idea on what is it) , is calling this SYSPROC.ADMIN_CMD to execute the queries, but it should be using a regular CLI interface instead.
I don't know what exactly tool you are using. but try to see if it has some sort of settings, so you can change that behavior.
Here is the list of admin cmds that ADMIN_CMD proc can execute:
https://www.ibm.com/support/knowledgecenter/en/SSEPGG_11.1.0/com.ibm.db2.luw.sql.rtn.doc/doc/r0012547.html .
as you can see, no SELECT statement there.
If I try to execute a simple SELECT , using this SP, I get the same error, from db2 CLP window, directly at the server.
db2 "call SYSPROC.ADMIN_CMD('SELECT * FROM DEPARTMENT')"
SQL0104N An unexpected token "SELECT" was found following
"BEGIN-OF-STATEMENT". Expected tokens may include: "ADD". SQLSTATE=42601
Regards
Samuel Pizarro
Ok
I had a closer look at the image error you posted...
the query is wrong. It's not exactly the same queries you posted in your question.
Have a closer look at the image error, and you will see that the Fetch and Rows words are double-quoted.
SELECT ... FROM WHERE (...) "Fetch" First 95 "Rows" Only
Remove the double-quotes from them.
If you are not writing them like that, so, it looks your tool is "changing" it, before submitting to the db2 engine. Again, not a db2 server issue.
Regards

How to convert this simple Entity Framework query into a standard SQL query?

I have no experience with the .NET Entity Framework and I have some doubts about what exactly do this query:
using (MyCorpo.EarlyWarnings.Model.EarlyWarningsEntities context = new Model.EarlyWarningsEntities())
{
DBContext.SetTimeout(context);
model.VulnerabilitySeverityAverage = (from x in context.VulnerabilityAlertDocuments select x.Severity).Average();
}
(Where the type of the model.VulnerabilitySeverityAverage is simply a string)
So I think that VulnerabilityAlertDocuments map the VulnerabilityAlertDocument database table because into the EarlyWarningsEntities I have something this line:
public DbSet<VulnerabilityAlertDocument> VulnerabilityAlertDocuments { get; set; }
So I am executing a query on the VulnerabilityAlertDocuments DbSet object that represent a query on my VulnerabilityAlertDocument table on my database. Is it correct?
So what exatly do the previous query?
I think that it select the Severity field value of all records in the VulnerabilityAlertDocument table and calculate the avarage value from all these value.
Is it my reasoning correct?
How can I convert this entity query in a classic SQL query? Someone can help me?
Tnx
How can I convert this entity query in a classic SQL query?
To see actual SQL you can just call .ToString() method on your query;
var sql = (from x in context.VulnerabilityAlertDocuments select x.Severity).Average().ToString();
So I am executing a query on the VulnerabilityAlertDocuments DbSet
object that represent a query on my VulnerabilityAlertDocument table
on my database. Is it correct?
Yes
So what exatly do the previous query?
Your query will average value in Severity column of ValnerabilityAlertDocuments table.
your translated query would've looked simular to this:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
AVG([Extent1].[Severity]) AS [A1]
FROM [dbo].[ValnerabilityAlertDocuments] AS [Extent1]
) AS [GroupBy1]
Also you could try to use such tool as SQL Server Profiler
UPDATE:
Just adding LinqPad to list of tools (thanks to Dismissile)
Select Average(x.Severity)
From VulnerabilityAlertDocuments x
Thats assuming your table is called "VulnerabilityAlertDocuments"
try again

Rewrite SQL to FluentNHibernate

I'am using NHibernate 3.3.1.4000 and FluentNHibernate 1.3.0.733 with SQL Server 2012 and I need to rewrite query to IQueryOver to do this calculation on server side without stored procedure calling.
WITH CTE_Links AS
(
SELECT Article1, MIN(Article2) Article2
FROM dbo.LinkBetweenArticles
GROUP BY Article1
HAVING Article1 > MIN(Article2)
)
SELECT COUNT(*)
FROM dbo.ArticlePlacedBySeller a
LEFT JOIN CTE_Links l ON a.Id = l.Article1
WHERE l.Article2 IS NULL
AND ConfirmedPosition_Id = 1000
Script description can be read here if you need
as far as I know it is not possible to use natively IQueryOver API to achieve this. IMHO you could use this CTE query as a custom query. You can find the solution by following the link http://refactoringaspnet.blogspot.com/2011/04/using-common-table-expressions-to.html.

Combining LINQ queries with entity framework C#

I have a linq query which selects several fields from my Customer table.
Applied to this method are multiple filters, using Func<IQueryable<T>, IQueryable<T>> with .Invoke.
The original query is essentially select * from customer.
The filter method is essentially select top 10
The output SQL is select top 10 from (select * from customer)
My customer table has over 1,000,000 rows which causes this query to take about 7 seconds to execute in SSMS. If I alter the output SQL to select top 10 from (select top 10 * from customer) by running it in SSMS then the query is instant (as you'd expect).
I am wondering if anyone knows what might cause LINQ to not combine these in a nice way, and if there is a best practice/workaround I can implement.
I should note that my actual code isn't select * it is selecting a few fields, but there is nothing more complex.
I am using SQL Server 2008 and MVC 3 with entity framework (not sure what version)
Edit: I should add, it's IQueryable all the way, nothing is evaluated until the end, and as a result the long execution is confined to that single line.
I don't know why it's not being optimised.
If the filter method really is equivalent to SELECT TOP 10 then you should be able to do it like this:
return query.Take(10);
which would resolve to select top 10 * from customer rather than the more convoluted thing you ended up with.
If this won't work then I'm afraid I'll need a little more detail.
EDIT: To clarify, if you do this in LINQ:
DataItems.Take(10).Take(10)
you would get this SQL:
SELECT TOP (10) [t1].[col1], [t1].[col2]
FROM (
SELECT TOP (10) [t0].[col1], [t0].[col2]
FROM [DataItem] AS [t0]
) AS [t1]
So if you can somehow use a Take(n) you will be okay.

converting a SQL statement to LINQ query on a DataTable

I am studying that Linq to DataTable,Lambda.
Because is difficult want to change sql to linq,Lambda, is not doing.
Below the SQL code is member list that remove telephone number repetition.
I will thank if help.
SELECT A.no, B.name, B.userId, B.homeTel2
FROM
( SELECT homeTel2, min(no) NO
FROM OF_Member
GROUP BY homeTel2
) A
INNER JOIN OF_Member B
ON A.NO = B.NO
Progressing work ============
var objectName =from t in mMemberTable.AsEnumerable()
group t by t.Field("homeTel2")
Try this link:
Linq to Entities simple group query
converting ms sql “group by” query to linq to sql
var objectName =from t in mMemberTable.AsEnumerable()
group t by t.Field<string>("homeTel2") into groups
select groups;
Hope this helps,
Regards
Try using a tool called LINQ Pad. This is the best tool so far for writing and testing sql/LINQ queries and moreover it is free. It also allows you to convert your queries from LINQ to SQL and vice-versa.
http://www.linqpad.net

Categories