nhibernate intercept select query - nhibernate

I'm looking at the nhibernate interceptor. It seems to be able to intercept save, update and delete queries but is there anyway I can intercept a select query.
The problem I have is that I automatically want to append some additional sql filters to the executing sql statement in certain cases.
Any thoughts
Thanks
Mat

The interceptor framework only allows you to intercept entity operations like save, update, and delete. Queries themselves aren't intercepted, only entity operations (and selecting/viewing doesn't count).
Consider using some sort of inheritance for a set of query classes that append to your ICriteria to suit your purposes.

I think you can accomplish that with a custom NHibernate persister; however, I'm having trouble finding examples on how you'd write one...

You can use the where attribute on the class tag:
<class name="MyClass" where="deleted=0">
...
</class>

Related

How do you map a HasOne relationship with nHibernate Fluent mapping and avoid N+1?

I have 2 tables ATable and AATable where both have a shared Primary Key - ATable.aKey and AATable.aKey to represent a one-to-one relationship. For my Fluent mapping I have a HasOne Relationship defined within my Fluent ATableMapping, all of which works fine. However I have noticed that querying for ATable generates a 2nd query (N+1) for the child Table AATable. My understanding is that Hasone eager loads by default, and I had assumed this would be part of the query for ATable, but I may well have this wrong?
I have researched various solutions including using .Not.LazyLoad().Fetch.Join(), PropertyRef, ForeignKey but I cannot seem to resolve the n+1 so that either it is Eager loaded with 1 query, or Lazy loaded and I can fetch the child with my queries.
Has anyone had any issues with this or have an example they know to work with no n+1? Grateful for any advice.
You have two options:
Not.LazyLoad() which disables possibility to provide lazy loaded related entity and it would enforce NHB to provide corresponding subselect within original query
Use component mapping so both entities point to the same table. This is better approach as once you decided to fetch both entities together, generated queries hit only one table - not two like within first option. This is definitely better for performance.

NHibernate produces multiple queries on deletion of object in child collection

I have an object hierarchy as follows:
Object
Reports
Report Items
Based on other posts here, I set the Report.ReportItems mapping to Inverse, and CascadeAllDeleteOrphan. This makes it so when I remove a Report from an Object it goes to erase the ReportItems in that report.
The way it does it is very inefficient. It basically does a Delete ... Where ReportItemID = ?.
I've seen suggestions to increase the batch size to prevent this from being done in too many round trips, but that seems like a sloppy fix. Is there a way to make NHibernate generate a query like this instead:
Delete ... Where ReportID = ?
This way it would execute one query that would delete all the ReportItems instead of one statement per ReportItem.
Thanks in advance.
Edit
I have heard from a few people that NHibernate will simply not work this way with standard QueryOver etc.
I decided to start using HQL to fix the problem. I will later use some reflection to make sure there are no "magic strings" being used.
I had the idea to:
Use HQL to mass-delete the Report Items
Tell the Session to Refresh the object so it could detect that the Report Items are gone
Then tell the session to erase the Report, and let it clean up the remaining information
This does not work though. You can see the code below:
Session.CreateQuery("delete ReportItem r where r.Report= :report").SetEntity("report", SelectedReport).ExecuteUpdate()
Session.Refresh(SelectedReport)
Object.Reports.Remove(SelectedReport)
Session.Delete(SelectedReport)
Session.Update(Object)
I have also tried doing a Session.Evict after performing the HQL statements, but NHibernate keeps using the cache to try to delete the ReportItems. Any tips on how to do this?
If your foreign key has delete rule set to cascade then you can tell NH not to generate DELETE statements for child items when the parent is deleted. In this case NH will generate DELETE statement only for parent entity.
<bag name="ReportItems" cascade="all-delete-orphan" inverse="true">
<key column="report_id" on-delete="cascade" />
<one-to-many class="ReportItem" />
</bag>
After a lot of research I have found that this is simply not possible. You can use HQL, raw SQL statements, or rely on database rules to perform the deletes by enforcing a relationship. However, there is no way to tell NHibernate to delete a list of objects based on their owner's ID.

NHibernate returning duplicate rows from hql named query with object constructors

I have a named hql query which makes use of object constructors for an object that is not mapped (it is only imported)
e.g.
select distinct new NotMappedResultClass(ah.SomeProp1, ah.SomeProp2)
from SomeMappedClass
where ...
order by ah.SomeProp1
The weird thing is, that when I call IQuery.List() in NHibernate, I end up with exactly twice as many rows from NHibernate than from the query that NHibernate ran (traced using SqlProfiler).
(In case it matters, the "where" clause does actually involve some subqueries).
Why is NHibernate duplicating the rows coming back from the database?
(I am using NHibernate 1.2.1.4000)
Found the problem.
My project has some odd mappings when it comes to inherited classes.
Basically, SomeMappedClass was abstract, and had its own NHibernate mapping, and there was a derived class SomeDerivedClass (that didn't add any functionality) that was also mapped separately without the "extends" attribute.
This caused NHibernate to issue two sql queries, with different aliases for the same table.
In my case the simple quick and dirty solution was to query from SomeDerivedClass instead of SomeMappedClass, but the more appropriate solution would probably be to modify the mappings / object inheritance.

Triggers in NHibernate

I'd like to know if is there something like a Trigger (of databases) in NHibernate that I can use per entity ?
I'd like to make a history of each record, and with triggers I can compare the old value and new value of each property and generate a register of history.
I've heard about Audit in NHibernate, but it's for all entities, if there isn't another way... how Can I separete a block per entity ?
Thanks

Override delete behaviour in NHibernate

In my application users cannot truly delete records. Rather, the record's Deleted field gets set to 1, which hides it from selects.
I need to maintain this behaviour and I'm looking into whether NHibernate is appropriate for my app. Can I override NHibnernate's delete behaviour so that instead of issuing DELETE statements, it issues UPDATES, as described above?
I would obviously also need to override its SELECT behaviour to include the 'AND Deleted = 0' clause. Or read from a view instead. I'm not sure.
To implement a soft delete just bypass the Hibernate delete mechanism. Instead, map your table's Deleted field to a .Net boolean property by the same name. To delete an item, set item.Deleted = true. Then add a where attribute to your class mapping to filter out the deleted items. If you like, create another mapping for deleted items. Otherwise they will become invisible to your application, but maybe that's what you want.
Edit: Here is perhaps a better approach: use the <sql-delete> tag to write a custom delete operation for your mapping. See http://docs.jboss.org/hibernate/core/3.3/reference/en/html/querysql.html#querysql-cud. I think this in combo with the where attribute would be just the ticket. For example:
<class name="MyClass" table="my_table" where="deleted=0">
...
<sql-delete>UPDATE my_table SET deleted=1 WHERE id=?</sql-delete>
</class>
I implemented this using INSTEAD OF DELETE triggers on SQL Server to set a delete flag bit when a SQL DELETE is issued. This has two benefits: 1) I can just issue deletes from my app. without worry and 2) It enforces soft deletes for all database access (i.e. the trigger must be temporarily disabled to hard delete). I then set up views that select the active records only and mapped NHibernate to those. This solution has worked very well for me.
I think the best way to get such behaviour would be by implementing the IInterceptor interface which would allow you to perform your own code as shown within the NHibernate Documentation.
Otherwise, you could simply create a trigger on delete that would perform an update. This solution is simpler, but is this suitable for your needs?
As for the SELECT, you only need to write method that will use Criterion with a Where clause to specify the Deleted=0 thing.