NHibernate createQuery with colons from method cal - nhibernate

I get a Antlr.Runtime.NoViableAltException thrown when trying to run the following query in NHibernate.
IQuery query = session.CreateQuery("from <table> where 1 in (select <column>.STIntersects(geography::STGeomFromText('POINT(:longitude :latitude)', 4326)))");
I'm setting longitude and latitude in setQuery.
my assumption is the :: in calling geography::STGeomFromText... because it's thinking it's a query parameter. Is there a way to escape the :?
This query works in my SQL Manager Studio.
Thanks!

Does NHIbernate support the STIntersects method ?
What you could do, is let NHibernate execute a (native) SQL query, like this:
ISQLQuery query = session.CreateSQLQuery ("your sql statement goes here");
query.AddEntity (typeof(TheEntityTypeThatYouWant));
var result = query.List<TheEntityTypeThatYouWant>();

See this post for some more info: Using SQL Server 2008 Geography types with nHibernate's CreateSQLQuery

Just to share what I ended up doing was taking the ADO connection out of the NHibernate session, performing a SqlCommand directly and manually built my Model objects from the results. It sucks, but it works. The connection still managed by NHibernate correctly.

Related

Need to identify C# Method That Is Generating Long Running Query

Is there a way to identify what method in C# code is connecting and executing a query?
My thoughts so far is to generate a unique user for each connection in the application and then examine the SQL Server system tables to view the original_login_user.
I should note that I am using Azure SQL.
The OP is using Entity Framework, and you can log all SQL Queries that EF performs by doing something like
using (var context = new BlogContext())
{
context.Database.Log = Console.Write;
// your code here...
}
See the following for more information: https://msdn.microsoft.com/en-us/library/dn469464(v=vs.113).aspx

Under what circumstances will nhibernate run queries without parameters?

During a pen-test of an in-development app, I had a scary result where there was a successful SQL injection due to NH executing a query without parameters and instead injecting a string right into the query.
We're using NHibernate 4 and Fluent NHibernate 1.4. Dialect is SQL 2008 running against SQL Azure.
The successful query looked like this (pulled from SQL Azure audit logs)
select columns from [Table] table0_ where table0_.TenantId='1555%00';IF(5672=5672) SELECT 5672 ELSE DROP FUNCTION GziQ--' and table0_.Active=1
As you can see, the injectable string was able to terminate the string and inject a DROP FUNCTION then comment out the rest of the statement.
Running this locally and using NHibernate Profiler, we see the value being passed as a parameter as-expected:
select columns from [Table] table0_ where table0_.TenantId = #p0 and table0_.Active=1
On the code side, the data is queried using an IQueryable interface (code inlined and simplified for example purposes):
Session.Query<TEntityType>().Cachable().Table.SingleOrDefault(k => k.TenantId == tenantId && k.Active);
Under what circumstanes would NHibernate not parameterize this query and instead inject the string directly into a plain SQL statement?

NHibernate - Is it possible to apply filters on UPDATE/DELETE?

I know that we can easily apply filters to query with additional where conditions with NHibernate, but is it possible to apply a filter when doing an update or delete?
If it is, how can I achieve that?
Yes it is possible, using HQL (Hibernate Query Language)
Here's an example of a batch update
IQuery updateQuery = this.Session.CreateQuery("update TransferItem set Status = :newStatus where Status = :oldStatus")
.SetParameter("oldStatus", DownloadStatus.Active)
.SetParameter("newStatus", DownloadStatus.Queued);
updateQuery.ExecuteUpdate();
NHibernate applies the configured mappings to create and run the following SQL:
update cms_TransferItem set Status=#p0 where Status=#p1
Here's an example of a batch delete
IQuery deleteQuery = this.Session.CreateQuery("delete TransferItem ti WHERE ti.Status = :statusToGo")
.SetParameter("statusToGo", DownloadStatus.Completed);
deleteQuery.ExecuteUpdate();
Which executes SQL like this:
delete from cms_TransferItem where Status=#p0
You might ask, if you have to work with a query language, why not just write raw SQL? When you use HQL you are working with the conceptual business objects that the rest of the .NET code is working with. The benefits of an ORM tool is that, for much of the code, the database tables and object-to-table mappings are abstracted away. With HQL you are continuing to interact with the object layer, rather than directly with the database tables.

Hibernate and dry-running HQL queries statically

I'd like to "dry-run" Hibernate HQL queries. That is I'd like to know what actual SQL queries Hibernate will execute from given HQL query without actually executing the HQL query against real database.
I have access to hibernate mapping for tables, the HQL query string, the dialect for my database. I have also access to database if that is needed.
Now, how can I find out all the SQL queries Hibernate can generate from my HQL without actually executing the query against any database? Are there any tools for this?
Note, that many SQL queries can be generated from one HQL query and the set of generated SQL queries may differ based on the contents of database.
I am not asking how to log SQL queries while HQL query is executing.
Edit: I don't mind connecting to database to fetch some metadata, I just don't want to execute queries.
Edit: I also know what limits and offsets are applied to query. I also have the actual parameters that will be bind to query.
The short answer is "you can't". The long answer is below.
There are two approaches you can take:
A) Look into HQLQueryPlan class, particularly its getSqlStrings() method. It will not get you the exact SQL because further preprocessing is involved before query is actually executed (parameters are bound, limit / offset are applied, etc...) but it may be close enough to what you want.
The thing to keep in mind here is that you'll need an actual SessionFactory instance in order to construct HQLQueryPlan, which means you won't be able to do so without "connecting to any database". You can, however, use in-memory database (SqlLite and the likes) and have Hibernate auto-create necessary schema for it.
B) Start with ASTQueryTranslatorFactory and descend into AST / ANTLR madness. In theory you may be able to hack together a parser that would work without relying on metadata but I have a hardest time imagining what is it you're trying to do for this to be worth it. Perhaps you can clarify? There has to be a better approach.
Update: for an offline, dry-run of some HQL, using HQLQueryPlan directly is a good approach. If you want to intercept every query in the app, while it's running, and record the SQL, you'll have to use proxies and reflection as described below.
Take a look at this answer for Criteria Queries.
For HQL, it's the same concept - you have to cast to Hibernate implementation classes and/or access private members, so it's not a supported method, but it will work with a the 3.2-3.3 versions of Hibernate. Here is the code to access the query from HQL (query is the object returned by session.createQuery(hql_string):
Field f = AbstractQueryImpl.class.getDeclaredField("session");
f.setAccessible(true);
SessionImpl sessionImpl = (SessionImpl) f.get(query);
Method m = AbstractSessionImpl.class.getDeclaredMethod("getHQLQueryPlan", new Class[] { String.class, boolean.class });
m.setAccessible(true);
HQLQueryPlan plan = (HQLQueryPlan) m.invoke(sessionImpl, new Object[] { query.getQueryString(), Boolean.FALSE });
for (int i = 0; i < plan.getSqlStrings().length; ++i) {
sql += plan.getSqlStrings()[i];
}
I would wrap all of that in a try/catch so you can go on with the query if the logging doesn't work.
It's possible to proxy your session and then proxy your queries so that you can log the sql and the parameters of every query (hql, sql, criteria) before it runs, without the code that builds the query having to do anything (as long as the initial session is retrieved from code you control).

Where can i see the query generated by subsonic?

I need to see how subsonic generates the SQL Query string.
I either have Sql Profile listening on the database or if you're in debug mode with VS you can move the cursor over the linq statement and it is in the tooltip.
THIS WILL WORK FOR SUBSONIC 2.X ONLY
When you create query like this:
var q = new Select()
.From(TableName.Schema)
.Where(TableName.Columns.ColumnName)
.IsEqualTo(SOME_VALUE).Or(TableName.Columns.OtherColumn)
.IsEqualTo(OTHER_VALUE)
......;
you can dump SQL Query to somewhere or break after this line to view it in Debug Visualizer:
Debug.WriteLine(q.SQLCommand);