<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://nhforge.org/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Simple audit metadata and logical deletion of business entities</title><link>http://nhforge.org/wikis/howtonh/simple-audit-metadata-and-logical-deletion-of-business-entities.aspx</link><description>Quick starts, tutorials, code snippets, custom user types, application blocks and more...</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Simple audit metadata and logical deletion of business entities</title><link>http://nhforge.org/wikis/howtonh/simple-audit-metadata-and-logical-deletion-of-business-entities.aspx</link><pubDate>Sun, 21 Jun 2009 00:44:39 GMT</pubDate><guid isPermaLink="false">45f813f2-f1c4-4eda-a619-288e3cadc793:63</guid><dc:creator>Raul Carlomagno</dc:creator><comments>http://nhforge.org/wikis/howtonh/simple-audit-metadata-and-logical-deletion-of-business-entities/comments.aspx</comments><description>Current revision posted to How to by Raul Carlomagno on 20/06/2009 09:44:39 p.m.&lt;br /&gt;
&lt;h2&gt;Simple audit metadata and logical deletion of business entities&lt;/h2&gt;
&lt;div style="font-size: 90%;"&gt;Filed under: Audit, &lt;span style="text-decoration: line-through; color: red;"&gt;logical&lt;/span&gt; &lt;span style="text-decoration: line-through; color: red;"&gt;delete&lt;/span&gt;&lt;span style="background: SpringGreen;"&gt;filter&lt;/span&gt;, listener, &lt;span style="text-decoration: line-through; color: red;"&gt;filter&lt;/span&gt;&lt;span style="background: SpringGreen;"&gt;logical&lt;/span&gt; &lt;span style="background: SpringGreen;"&gt;delete&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;This article is just about a simple way to achieve auditing and perform logical delete of your sensible data, doing use of the listeners features of NHibernate. Design patterns and &lt;span style="text-decoration: line-through; color: red;"&gt;arquitecture&lt;/span&gt; &lt;span style="background: SpringGreen;"&gt;architecture&lt;/span&gt; principles are outside of the scope of the article, this is just an example, take it as a guide.&lt;/p&gt;
&lt;p&gt;Remember the old days when you had to audit data stored on your database, every time you build a query to insert, update or delete data, you had to &amp;ldquo;remember&amp;rdquo; to include the values for auditing (timestamp, user id). It was worse if you had stored procedures (by the way, i hate them) because suppose that was needed to take user credentials from another service to audit, you were limited by Transact-SQL language inside the stored procedure to access that service. Anyway, every time you build a query, you need those metadata values to store them, it could be good if you can centralize the place where you obtain and set those values (remember DRY).&lt;/p&gt;
&lt;p&gt;Maybe, in a strict way, auditing would take place in the business layer, but we are not going to miss this feature that NHibernate has for us, so auditing will take place in the data access layer. With NHibernate we can override its native methods when performing data access, NHibernate will fire events which we will have to override to audit the data and of course to do a logical deletion of our entities.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get inside the code and explain the domain. In the example we have a BaseEntity for any persistible entity, and then, for the auditable entities, the AuditableEntity which inherits from BaseEntity. We want to audit the cars inside the database. We will audit the date and time, the user, the IP address and the hostname for each action on the entity (insert, update, delete), i think this auditing metada is fine, you can add more of course, your fantasy is your limit.&lt;/p&gt;
&lt;p&gt;In fact this can&amp;rsquo;t be called audit, because we are not tracking changes of entities, just who did an action, when and from, pseudoaudit? [:D]&lt;/p&gt;
&lt;p&gt;&lt;a href="/wikis/howtonh/add.aspx/$image24.png"&gt;&lt;img title="image" style="display:inline;border-width:0px;border:0;" alt="image" src="http://i40.tinypic.com/16iijs.png" width="407" border="0" height="712" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;So, the example solution has a test fixture to test the purpose of the example. It was developed with NHibernate 2.1.0.2001.&lt;/p&gt;
&lt;p&gt;No more words, show me the code.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see the mapping files.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;Car.hbm.xml&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:411b4d59-2c28-4172-ab11-be3aabfc1650" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-mapping &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;urn:nhibernate-mapping-2.2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&lt;br /&gt;                   assembly&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&lt;br /&gt;                   namespace&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;class &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Car&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; table&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;cars&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;id &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Int64&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;generator &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;hilo&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;param &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;max_lo&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;50&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;param&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;generator&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;id&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;BrandName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;brand_name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModelName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;model_name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Kilometers&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;kilometers&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;      &lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#008000;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="color:#008000;"&gt;audit attributes&lt;/span&gt;&lt;span style="color:#008000;"&gt;--&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&lt;br /&gt;        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;added_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&lt;br /&gt;        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;modified_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&lt;br /&gt;        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;erased_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;filter &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;avoidLogicalDeleted&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; condition&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;erased_date IS NULL&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;br /&gt;  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;filter-def &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;avoidLogicalDeleted&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-mapping&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;It has the Id, 3 owned properties, and 9 properties for metadata auditing. The filter part is about logical deletes, we are going to talk about it in later. &lt;/p&gt;
&lt;p&gt;The &lt;b&gt;User.hbm.xml &lt;/b&gt;is really simple, we are not going to show it, it has no sense, anyway, the example solution can be downloaded.&lt;/p&gt;
&lt;p&gt;Now it&amp;rsquo;s time to show the NHibernate configuration file.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;hibernate.cfg.xml&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:3ba95b40-497a-4b28-8b49-14fc1742bf02" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-configuration  &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;urn:nhibernate-configuration-2.2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;session-factory&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;connection.driver_class&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;NHibernate.Driver.SqlClientDriver&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;connection.connection_string&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;      Server=(local)\SQLEXPRESS;initial catalog=auditexample;Integrated Security=SSPI&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;adonet.batch_size&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;10&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;show_sql&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;false&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;dialect&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;NHibernate.Dialect.MsSql2005Dialect&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;query.substitutions&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;true 1, false 0, yes &amp;#39;Y&amp;#39;, no &amp;#39;N&amp;#39;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;proxyfactory.factory_class&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;        NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;mapping &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;assembly&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;listener &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.NHExtensions.CustomSaveUpdateEventListener, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&lt;br /&gt;        type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;save-update&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;listener &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.NHExtensions.CustomDeleteEventListener, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&lt;br /&gt;        type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;    &lt;br /&gt;  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;session-factory&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-configuration&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s analyze it, in the configuration file there is an attribute that is not so common, the listener attribute, as we mention before, with these attributes we are forcing NHibernate to lookup for the custom event listener that we inherited from the default listeners for ISession.Delete() and ISession.SaveUpdate() methods. Inside both class CustomSaveUpdateEventListener and CustomDeleteEventListener will appear a class called SecurityContext which handles the metada for auditing, this class will be discused later, after explaining both listeners.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;CustomSaveUpdateEventListener.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:e2d0d747-e26f-4d1c-a83b-59a459662651" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; CustomSaveUpdateEventListener : DefaultSaveOrUpdateEventListener&lt;br /&gt;{&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; PerformSaveOrUpdate(SaveOrUpdateEvent evt)&lt;br /&gt;   {&lt;br /&gt;       var entity &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; evt.Entity &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;as&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditableEntity;&lt;br /&gt;&lt;br /&gt;          &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (entity &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;){&lt;br /&gt;              &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (entity.Id &lt;/span&gt;&lt;span style="color:#000000;"&gt;==&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;)&lt;br /&gt;                  ProcessEntityForInserting(entity);&lt;br /&gt;              &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;                  ProcessEntityForUpdating(entity);&lt;br /&gt;          }&lt;br /&gt;       &lt;br /&gt;          &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;base&lt;/span&gt;&lt;span style="color:#000000;"&gt;.PerformSaveOrUpdate(evt);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;internal&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;virtual&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForInserting(AuditableEntity entity)&lt;br /&gt;    {&lt;br /&gt;       entity.AddedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;&lt;br /&gt;       entity.AddedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;       entity.AddedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();&lt;br /&gt;       entity.AddedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;internal&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;virtual&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForUpdating(AuditableEntity entity)&lt;br /&gt;    {&lt;br /&gt;       entity.ModifiedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;&lt;br /&gt;       entity.ModifiedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;       entity.ModifiedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();&lt;br /&gt;       entity.ModifiedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();&lt;br /&gt;    }&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;h4&gt;&lt;b&gt;CustomDeleteEventListener.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:0d9f2bf9-3a0b-4402-832d-e0e844f30d37" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; CustomDeleteEventListener : DefaultDeleteEventListener&lt;br /&gt;{&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; DeleteEntity(IEventSource session, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; entity,&lt;br /&gt;                        NHibernate.Engine.EntityEntry entityEntry,&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color:#000000;"&gt; isCascadeDeleteEnabled,&lt;br /&gt;                        NHibernate.Persister.Entity.IEntityPersister persister,&lt;br /&gt;                        Iesi.Collections.ISet transientEntities)&lt;br /&gt;   {&lt;br /&gt;        var auditableEntity &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; entity &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;as&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditableEntity;&lt;br /&gt;&lt;br /&gt;           &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (auditableEntity &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;){&lt;br /&gt;              ProcessEntityForLogicalDelete(auditableEntity);&lt;br /&gt;               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.CascadeBeforeDelete(session, persister, entity,&lt;br /&gt;                   entityEntry, transientEntities);&lt;br /&gt;               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.CascadeAfterDelete(session, persister, entity,&lt;br /&gt;                   transientEntities);&lt;br /&gt;       } &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt; {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;normal delete&lt;/span&gt;&lt;span style="color:#008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;base&lt;/span&gt;&lt;span style="color:#000000;"&gt;.DeleteEntity(session, entity, entityEntry,&lt;br /&gt;                isCascadeDeleteEnabled, persister, transientEntities);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForLogicalDelete(AuditableEntity entity)&lt;br /&gt;   {&lt;br /&gt;        entity.ErasedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;&lt;br /&gt;        entity.ErasedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;        entity.ErasedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();&lt;br /&gt;        entity.ErasedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();&lt;br /&gt;   }&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;h4&gt;&lt;b&gt;SecurityContext.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:64c46d35-180d-4eea-b740-092564076a3d" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color:#008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; Ridiculous simple crosscut security class to get user credentials and audit metadata&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color:#808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext&lt;br /&gt;{&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;maybe System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString(), you decide&lt;/span&gt;&lt;span style="color:#008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; User LoggedUser {&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;;}&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; GetHostName()&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; Dns.GetHostName();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; GetHostIP()&lt;br /&gt;   {&lt;br /&gt;        IPAddress[] addresses &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; Dns.GetHostAddresses(Dns.GetHostName());&lt;br /&gt;        &lt;br /&gt;        &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;be carefull and filter the public ip, use the local one&lt;br /&gt;        &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;and of course, this has no sense for an httpcontext, use remote host ip instead&lt;/span&gt;&lt;span style="color:#008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (addresses.Length &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;)&lt;br /&gt;            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; addresses[&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;].ToString();&lt;br /&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;   }&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;This class is just a simple helper to get the metadata needed for auditing, in this example it holds the session of the logged user too.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:a58b502c-190d-4d18-9988-4eed1524b883" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#000000;"&gt;[TestFixture]&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditTest&lt;br /&gt;{&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; Configuration _configuration;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; ISessionFactory _sessionFactory;&lt;br /&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; User _sampleUser1;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; User _sampleUser2;&lt;br /&gt;&lt;br /&gt;   [TestFixtureSetUp]&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestFixtureSetUp()&lt;br /&gt;   {&lt;br /&gt;       XmlConfigurator.Configure();&lt;br /&gt;&lt;br /&gt;       _configuration &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Configuration();&lt;br /&gt;       _configuration.Configure();&lt;br /&gt;       _sessionFactory &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _configuration.BuildSessionFactory();&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;drop all tables on database&lt;/span&gt;&lt;span style="color:#008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;       _sessionFactory.OpenSession().CreateSQLQuery(&lt;br /&gt;               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;IF OBJECT_ID (N&amp;#39;dbo.cars&amp;#39;, N&amp;#39;U&amp;#39;) IS NOT NULL DELETE cars&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;        ).ExecuteUpdate();&lt;br /&gt;       &lt;br /&gt;       _sessionFactory.OpenSession().CreateSQLQuery(&lt;br /&gt;               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;IF OBJECT_ID (N&amp;#39;dbo.users&amp;#39;, N&amp;#39;U&amp;#39;) IS NOT NULL DELETE users&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;        ).ExecuteUpdate();&lt;br /&gt;       &lt;br /&gt;       _sessionFactory.OpenSession().CreateSQLQuery(&lt;br /&gt;               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;EXEC sp_MSforeachtable ?&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;        ).SetParameter(&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;,&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;DROP TABLE ?&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;).ExecuteUpdate();&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SchemaExport(_configuration).Create(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;false&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;true&lt;/span&gt;&lt;span style="color:#000000;"&gt;);&lt;br /&gt;&lt;br /&gt;       PrepareLoggedUsers();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   [TestFixtureTearDown]&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestFixtureTearDown()&lt;br /&gt;   {&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;new SchemaExport(_configuration).Drop(false, true);&lt;/span&gt;&lt;span style="color:#008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;       _sessionFactory.Close();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   [SetUp]&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestSetUp()&lt;br /&gt;   {&lt;br /&gt;       _sessionFactory.OpenSession().CreateQuery(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;delete Car&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;).ExecuteUpdate();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; PrepareLoggedUsers()&lt;br /&gt;   {&lt;br /&gt;       _sampleUser1 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; User() { Login &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;rcarlomagno&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Name &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Raul&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,&lt;br /&gt;               LastName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Carlomagno&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Password &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;jijiji&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; };&lt;br /&gt;       _sampleUser2 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; User() { Login &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ndaponte&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Name &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Nadia&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,&lt;br /&gt;               LastName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Daponte&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Password &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;jujujuju&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; };&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())&lt;br /&gt;       {&lt;br /&gt;           session.Save(_sampleUser1);&lt;br /&gt;           session.Save(_sampleUser2);&lt;br /&gt;           transaction.Commit();&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sampleUser1;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   [Test]&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditAddedEntity()&lt;br /&gt;   {&lt;br /&gt;       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Renault&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Clio&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,&lt;br /&gt;               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;110000&lt;/span&gt;&lt;span style="color:#000000;"&gt; };&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())&lt;br /&gt;       {&lt;br /&gt;           session.SaveOrUpdate(car);&lt;br /&gt;           transaction.Commit();&lt;br /&gt;           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);&lt;br /&gt;&lt;br /&gt;       Assert.IsNotNull(car);&lt;br /&gt;       Assert.IsNotNull(car.AddedDate);&lt;br /&gt;       Assert.IsNotNull(car.AddedBy);&lt;br /&gt;       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.AddedFromHostName));&lt;br /&gt;       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.AddedFromIP));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   [Test]&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditModifiedEntity()&lt;br /&gt;   {&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Ford&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Ka&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;97544&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;&lt;br /&gt;       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName,&lt;br /&gt;               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers };&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())&lt;br /&gt;       {&lt;br /&gt;           session.SaveOrUpdate(car);&lt;br /&gt;           transaction.Commit();&lt;br /&gt;           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);&lt;br /&gt;&lt;br /&gt;       Assert.IsNotNull(car);&lt;br /&gt;       Assert.IsNotNull(car.AddedDate);&lt;br /&gt;       Assert.IsNotNull(car.AddedBy);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;let&amp;#39;s change logged user and wait 2 seconds to change the car&amp;#39;s data&lt;/span&gt;&lt;span style="color:#008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;       SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sampleUser2;&lt;br /&gt;       Thread.Sleep(&lt;/span&gt;&lt;span style="color:#800080;"&gt;2000&lt;/span&gt;&lt;span style="color:#000000;"&gt;);&lt;br /&gt;&lt;br /&gt;       car.Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;54000&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;       car.ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Fiesta&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())&lt;br /&gt;       {&lt;br /&gt;           session.SaveOrUpdate(car);&lt;br /&gt;           transaction.Commit();&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);&lt;br /&gt;&lt;br /&gt;       Assert.IsNotNull(car);&lt;br /&gt;       Assert.IsNotNull(car.ModifiedBy);&lt;br /&gt;       Assert.IsNotNull(car.ModifiedDate);&lt;br /&gt;       Assert.AreNotEqual(car.ModifiedDate, car.AddedDate);&lt;br /&gt;       Assert.AreNotEqual(car.ModifiedBy, car.AddedBy);&lt;br /&gt;       Assert.AreNotEqual(car.Kilometers, kilometers);&lt;br /&gt;       Assert.AreNotEqual(car.ModelName, modelName);&lt;br /&gt;       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ModifiedFromHostName));&lt;br /&gt;       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ModifiedFromIP));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   [Test]&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditErasedEntity()&lt;br /&gt;   {&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Citroen&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;C3&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;74665&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;&lt;br /&gt;&lt;br /&gt;       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName,&lt;br /&gt;               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers };&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())&lt;br /&gt;       {&lt;br /&gt;           session.SaveOrUpdate(car);&lt;br /&gt;           transaction.Commit();&lt;br /&gt;           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())&lt;br /&gt;       {&lt;br /&gt;           session.Delete(car);&lt;br /&gt;           transaction.Commit();&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);&lt;br /&gt;&lt;br /&gt;       Assert.IsNotNull(car);&lt;br /&gt;       Assert.IsNotNull(car.ErasedBy);&lt;br /&gt;       Assert.IsNotNull(car.ErasedDate);&lt;br /&gt;       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ErasedFromHostName));&lt;br /&gt;       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ErasedFromIP));&lt;br /&gt;&lt;br /&gt;       ISession tmpSession &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession();&lt;br /&gt;       tmpSession.EnableFilter(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;avoidLogicalDeleted&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);&lt;br /&gt;       Assert.AreEqual(&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;, tmpSession.CreateCriteria&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;().List().Count);&lt;br /&gt;       tmpSession.DisableFilter(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;avoidLogicalDeleted&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);&lt;br /&gt;       Assert.AreEqual(&lt;/span&gt;&lt;span style="color:#800080;"&gt;1&lt;/span&gt;&lt;span style="color:#000000;"&gt;, tmpSession.CreateCriteria&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;().List().Count);&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;This test fixture proves that i am not lying. :-)&lt;/p&gt;
&lt;p&gt;A few last words, in CanAuditErasedEntity() method, at the end of it, it is supposed that if we deleted logically an entity, we don&amp;rsquo;t want to see it in the results, so before doing a Criteria or HQL to get some data, we must enable the filter on the ISession, because filters are disabled by default. I do not know if there is a way to enable it on the ISessionFactory, to avoid manually enable it each time we want to get some data.&lt;/p&gt;
&lt;p&gt;Well, this is the first time i write an article, i hope the next will be better. Sorry for my english.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.2shared.com/file/6380003/67d562c8/AuditExample.html"&gt;Solution Download&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Simple audit metadata and logical deletion of business entities</title><link>http://nhforge.org/wikis/howtonh/simple-audit-metadata-and-logical-deletion-of-business-entities/revision/3.aspx</link><pubDate>Sat, 20 Jun 2009 05:56:26 GMT</pubDate><guid isPermaLink="false">45f813f2-f1c4-4eda-a619-288e3cadc793:288</guid><dc:creator>Raul Carlomagno</dc:creator><comments>http://nhforge.org/wikis/howtonh/simple-audit-metadata-and-logical-deletion-of-business-entities/comments.aspx</comments><description>Revision 3 posted to How to by Raul Carlomagno on 20/06/2009 02:56:26 a.m.&lt;br /&gt;
&lt;h2&gt;Simple audit metadata and logical deletion of business entities&lt;/h2&gt;
&lt;div style="font-size: 90%;"&gt;Filed under: Audit, logical delete, listener, filter&lt;/div&gt;

&lt;p&gt;This article is just about a simple way to achieve auditing and perform logical delete of your sensible data, doing use of the listeners features of NHibernate. Design patterns and arquitecture principles are outside of the scope of the article, this is just an example, take it as a guide.&lt;/p&gt;
&lt;p&gt;Remember the old days when you had to audit data stored on your database, every time you build a query to insert, update or delete data, you had to &amp;ldquo;remember&amp;rdquo; to include the values for auditing (timestamp, user id). It was worse if you had stored procedures (by the way, i hate them) because suppose that was needed to take user credentials from another service to audit, you were limited by Transact-SQL language inside the stored procedure to access that service. Anyway, every time you build a query, you need those metadata values to store them, it could be good if you can centralize the place where you obtain and set those values (remember DRY).&lt;/p&gt;
&lt;p&gt;Maybe, in a strict way, auditing would take place in the business layer, but we are not going to miss this feature that NHibernate has for us, so auditing will take place in the data access layer. With NHibernate we can override its native methods when performing data access, NHibernate will fire events which we will have to override to audit the data and of course to do a logical deletion of our entities.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get inside the code and explain the domain. In the example we have a BaseEntity for any persistible entity, and then, for the auditable entities, the AuditableEntity which inherits from BaseEntity. We want to audit the cars inside the database. We will audit the date and time, the user, the IP address and the hostname for each action on the entity (insert, update, delete), i think this auditing metada is fine, you can add more of course, your fantasy is your limit.&lt;/p&gt;
&lt;p&gt;In fact this can&amp;rsquo;t be called audit, because we are not tracking changes of entities, just who did an action, when and from, pseudoaudit? [:D]&lt;/p&gt;
&lt;p&gt;&lt;a href="/wikis/howtonh/add.aspx/$image24.png"&gt;&lt;img title="image" style="display:inline;border-width:0px;border:0;" alt="image" src="http://i40.tinypic.com/16iijs.png" width="407" border="0" height="712" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;So, the example solution has a test fixture to test the purpose of the example. It was developed with NHibernate 2.1.0.2001.&lt;/p&gt;
&lt;p&gt;No more words, show me the code.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see the mapping files.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;Car.hbm.xml&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:411b4d59-2c28-4172-ab11-be3aabfc1650" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-mapping &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;urn:nhibernate-mapping-2.2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
                   assembly&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
                   namespace&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;class &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Car&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; table&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;cars&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;id &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Int64&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;generator &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;hilo&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;param &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;max_lo&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;50&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;param&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;generator&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;id&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;BrandName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;brand_name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModelName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;model_name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Kilometers&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;kilometers&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      
    &lt;/span&gt;&lt;span style="color:#008000;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="color:#008000;"&gt;audit attributes&lt;/span&gt;&lt;span style="color:#008000;"&gt;--&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;added_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;modified_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;    
    
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;erased_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;filter &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;avoidLogicalDeleted&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; condition&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;erased_date IS NULL&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;filter-def &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;avoidLogicalDeleted&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-mapping&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;It has the Id, 3 owned properties, and 9 properties for metadata auditing. The filter part is about logical deletes, we are going to talk about it in later. &lt;/p&gt;
&lt;p&gt;The &lt;b&gt;User.hbm.xml &lt;/b&gt;is really simple, we are not going to show it, it has no sense, anyway, the example solution can be downloaded.&lt;/p&gt;
&lt;p&gt;Now it&amp;rsquo;s time to show the NHibernate configuration file.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;hibernate.cfg.xml&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:3ba95b40-497a-4b28-8b49-14fc1742bf02" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-configuration  &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;urn:nhibernate-configuration-2.2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;session-factory&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;connection.driver_class&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;NHibernate.Driver.SqlClientDriver&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;connection.connection_string&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      Server=(local)\SQLEXPRESS;initial catalog=auditexample;Integrated Security=SSPI
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;adonet.batch_size&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;10&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;show_sql&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;false&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;dialect&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;NHibernate.Dialect.MsSql2005Dialect&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;query.substitutions&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;true 1, false 0, yes &amp;#39;Y&amp;#39;, no &amp;#39;N&amp;#39;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;proxyfactory.factory_class&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;mapping &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;assembly&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;listener &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.NHExtensions.CustomSaveUpdateEventListener, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;save-update&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;listener &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.NHExtensions.CustomDeleteEventListener, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;    
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;session-factory&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-configuration&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s analyze it, in the configuration file there is an attribute that is not so common, the listener attribute, as we mention before, with these attributes we are forcing NHibernate to lookup for the custom event listener that we inherited from the default listeners for ISession.Delete() and ISession.SaveUpdate() methods. Inside both class CustomSaveUpdateEventListener and CustomDeleteEventListener will appear a class called SecurityContext which handles the metada for auditing, this class will be discused later, after explaining both listeners.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;CustomSaveUpdateEventListener.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:e2d0d747-e26f-4d1c-a83b-59a459662651" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; CustomSaveUpdateEventListener : DefaultSaveOrUpdateEventListener
{
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; PerformSaveOrUpdate(SaveOrUpdateEvent evt)
   {
       var entity &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; evt.Entity &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;as&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditableEntity;

          &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (entity &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;){
              &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (entity.Id &lt;/span&gt;&lt;span style="color:#000000;"&gt;==&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
                  ProcessEntityForInserting(entity);
              &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;
                  ProcessEntityForUpdating(entity);
          }
       
          &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;base&lt;/span&gt;&lt;span style="color:#000000;"&gt;.PerformSaveOrUpdate(evt);
   }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;internal&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;virtual&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForInserting(AuditableEntity entity)
    {
       entity.AddedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;
       entity.AddedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       entity.AddedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();
       entity.AddedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();
    }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;internal&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;virtual&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForUpdating(AuditableEntity entity)
    {
       entity.ModifiedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;
       entity.ModifiedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       entity.ModifiedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();
       entity.ModifiedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();
    }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;h4&gt;&lt;b&gt;CustomDeleteEventListener.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:0d9f2bf9-3a0b-4402-832d-e0e844f30d37" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; CustomDeleteEventListener : DefaultDeleteEventListener
{
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; DeleteEntity(IEventSource session, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; entity,
                        NHibernate.Engine.EntityEntry entityEntry,
                        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color:#000000;"&gt; isCascadeDeleteEnabled,
                        NHibernate.Persister.Entity.IEntityPersister persister,
                        Iesi.Collections.ISet transientEntities)
   {
        var auditableEntity &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; entity &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;as&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditableEntity;

           &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (auditableEntity &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;){
              ProcessEntityForLogicalDelete(auditableEntity);
               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.CascadeBeforeDelete(session, persister, entity,
                   entityEntry, transientEntities);
               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.CascadeAfterDelete(session, persister, entity,
                   transientEntities);
       } &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt; {
            &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;normal delete&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;base&lt;/span&gt;&lt;span style="color:#000000;"&gt;.DeleteEntity(session, entity, entityEntry,
                isCascadeDeleteEnabled, persister, transientEntities);
       }
   }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForLogicalDelete(AuditableEntity entity)
   {
        entity.ErasedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;
        entity.ErasedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
        entity.ErasedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();
        entity.ErasedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();
   }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;h4&gt;&lt;b&gt;SecurityContext.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:64c46d35-180d-4eea-b740-092564076a3d" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; Ridiculous simple crosscut security class to get user credentials and audit metadata
&lt;/span&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color:#808080;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext
{
    &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;maybe System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString(), you decide&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; User LoggedUser {&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;;}

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; GetHostName()
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; Dns.GetHostName();
    }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; GetHostIP()
   {
        IPAddress[] addresses &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; Dns.GetHostAddresses(Dns.GetHostName());
        
        &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;be carefull and filter the public ip, use the local one
        &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;and of course, this has no sense for an httpcontext, use remote host ip instead&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (addresses.Length &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; addresses[&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;].ToString();
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
   }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;This class is just a simple helper to get the metadata needed for auditing, in this example it holds the session of the logged user too.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:a58b502c-190d-4d18-9988-4eed1524b883" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#000000;"&gt;[TestFixture]
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditTest
{
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; Configuration _configuration;
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; ISessionFactory _sessionFactory;

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; User _sampleUser1;
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; User _sampleUser2;

   [TestFixtureSetUp]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestFixtureSetUp()
   {
       XmlConfigurator.Configure();

       _configuration &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Configuration();
       _configuration.Configure();
       _sessionFactory &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _configuration.BuildSessionFactory();

       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;drop all tables on database&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;       _sessionFactory.OpenSession().CreateSQLQuery(
               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;IF OBJECT_ID (N&amp;#39;dbo.cars&amp;#39;, N&amp;#39;U&amp;#39;) IS NOT NULL DELETE cars&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        ).ExecuteUpdate();
       
       _sessionFactory.OpenSession().CreateSQLQuery(
               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;IF OBJECT_ID (N&amp;#39;dbo.users&amp;#39;, N&amp;#39;U&amp;#39;) IS NOT NULL DELETE users&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        ).ExecuteUpdate();
       
       _sessionFactory.OpenSession().CreateSQLQuery(
               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;EXEC sp_MSforeachtable ?&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        ).SetParameter(&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;,&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;DROP TABLE ?&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;).ExecuteUpdate();

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SchemaExport(_configuration).Create(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;false&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;true&lt;/span&gt;&lt;span style="color:#000000;"&gt;);

       PrepareLoggedUsers();
   }

   [TestFixtureTearDown]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestFixtureTearDown()
   {
       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;new SchemaExport(_configuration).Drop(false, true);&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;       _sessionFactory.Close();
   }

   [SetUp]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestSetUp()
   {
       _sessionFactory.OpenSession().CreateQuery(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;delete Car&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;).ExecuteUpdate();
   }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; PrepareLoggedUsers()
   {
       _sampleUser1 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; User() { Login &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;rcarlomagno&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Name &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Raul&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,
               LastName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Carlomagno&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Password &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;jijiji&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; };
       _sampleUser2 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; User() { Login &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ndaponte&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Name &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Nadia&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,
               LastName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Daponte&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Password &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;jujujuju&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; };

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.Save(_sampleUser1);
           session.Save(_sampleUser2);
           transaction.Commit();
       }

       SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sampleUser1;
   }

   [Test]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditAddedEntity()
   {
       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Renault&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Clio&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,
               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;110000&lt;/span&gt;&lt;span style="color:#000000;"&gt; };
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.AddedDate);
       Assert.IsNotNull(car.AddedBy);
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.AddedFromHostName));
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.AddedFromIP));
   }

   [Test]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditModifiedEntity()
   {
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Ford&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Ka&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;97544&lt;/span&gt;&lt;span style="color:#000000;"&gt;;

       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName,
               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers };

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.AddedDate);
       Assert.IsNotNull(car.AddedBy);


       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;let&amp;#39;s change logged user and wait 2 seconds to change the car&amp;#39;s data&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;       SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sampleUser2;
       Thread.Sleep(&lt;/span&gt;&lt;span style="color:#800080;"&gt;2000&lt;/span&gt;&lt;span style="color:#000000;"&gt;);

       car.Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;54000&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       car.ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Fiesta&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.ModifiedBy);
       Assert.IsNotNull(car.ModifiedDate);
       Assert.AreNotEqual(car.ModifiedDate, car.AddedDate);
       Assert.AreNotEqual(car.ModifiedBy, car.AddedBy);
       Assert.AreNotEqual(car.Kilometers, kilometers);
       Assert.AreNotEqual(car.ModelName, modelName);
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ModifiedFromHostName));
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ModifiedFromIP));
   }

   [Test]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditErasedEntity()
   {
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Citroen&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;C3&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;74665&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;

       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName,
               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers };

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;
       }

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.Delete(car);
           transaction.Commit();
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.ErasedBy);
       Assert.IsNotNull(car.ErasedDate);
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ErasedFromHostName));
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ErasedFromIP));

       ISession tmpSession &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession();
       tmpSession.EnableFilter(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;avoidLogicalDeleted&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
       Assert.AreEqual(&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;, tmpSession.CreateCriteria&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;().List().Count);
       tmpSession.DisableFilter(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;avoidLogicalDeleted&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
       Assert.AreEqual(&lt;/span&gt;&lt;span style="color:#800080;"&gt;1&lt;/span&gt;&lt;span style="color:#000000;"&gt;, tmpSession.CreateCriteria&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;().List().Count);

   }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;This test fixture proves that i am not lying. :-)&lt;/p&gt;
&lt;p&gt;A few last words, in CanAuditErasedEntity() method, at the end of it, it is supposed that if we deleted logically an entity, we don&amp;rsquo;t want to see it in the results, so before doing a Criteria or HQL to get some data, we must enable the filter on the ISession, because filters are disabled by default. I do not know if there is a way to enable it on the ISessionFactory, to avoid manually enable it each time we want to get some data.&lt;/p&gt;
&lt;p&gt;Well, this is the first time i write an article, i hope the next will be better. Sorry for my english.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.2shared.com/file/6380003/67d562c8/AuditExample.html"&gt;&lt;span style="background: SpringGreen;"&gt;Solution&lt;/span&gt; &lt;span style="background: SpringGreen;"&gt;Download&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Simple audit metadata and logical deletion of business entities</title><link>http://nhforge.org/wikis/howtonh/simple-audit-metadata-and-logical-deletion-of-business-entities/revision/2.aspx</link><pubDate>Sat, 20 Jun 2009 05:47:25 GMT</pubDate><guid isPermaLink="false">45f813f2-f1c4-4eda-a619-288e3cadc793:287</guid><dc:creator>Raul Carlomagno</dc:creator><comments>http://nhforge.org/wikis/howtonh/simple-audit-metadata-and-logical-deletion-of-business-entities/comments.aspx</comments><description>Revision 2 posted to How to by Raul Carlomagno on 20/06/2009 02:47:25 a.m.&lt;br /&gt;
&lt;h2&gt;Simple audit metadata and logical deletion of business entities&lt;/h2&gt;
&lt;div style="font-size: 90%;"&gt;Filed under: Audit, logical delete, listener, filter&lt;/div&gt;

&lt;p&gt;This article is just about a simple way to achieve auditing and perform logical delete of your sensible data, doing use of the listeners features of NHibernate. Design patterns and arquitecture principles are outside of the scope of the article, this is just an example, take it as a guide.&lt;/p&gt;
&lt;p&gt;Remember the old days when you had to audit data stored on your database, every time you build a query to insert, update or delete data, you had to &amp;ldquo;remember&amp;rdquo; to include the values for auditing (timestamp, user id). It was worse if you had stored procedures (by the way, i hate them) because suppose that was needed to take user credentials from another service to audit, you were limited by Transact-SQL language inside the stored procedure to access that service. Anyway, every time you build a query, you need those metadata values to store them, it could be good if you can centralize the place where you obtain and set those values (remember DRY).&lt;/p&gt;
&lt;p&gt;Maybe, in a strict way, auditing would take place in the business layer, but we are not going to miss this feature that NHibernate has for us, so auditing will take place in the data access layer. With NHibernate we can override its native methods when performing data access, NHibernate will fire events which we will have to override to audit the data and of course to do a logical deletion of our entities.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get inside the code and explain the domain. In the example we have a BaseEntity for any persistible entity, and then, for the auditable entities, the AuditableEntity which inherits from BaseEntity. We want to audit the cars inside the database. We will audit the date and time, the user, the IP address and the hostname for each action on the entity (insert, update, delete), i think this auditing metada is fine, you can add more of course, your fantasy is your limit.&lt;/p&gt;
&lt;p&gt;In fact this can&amp;rsquo;t be called audit, because we are not tracking changes of entities, just who did an action, when and from, pseudoaudit? [:D]&lt;/p&gt;
&lt;p&gt;&lt;a href="/wikis/howtonh/add.aspx/$image24.png"&gt;&lt;span style="text-decoration: line-through; color: red;"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="image" src="/wikis/howtonh/add.aspx/$image_thumb16.png" width="407" border="0" height="712" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/wikis/howtonh/add.aspx/$image24.png"&gt;&lt;span style="background: SpringGreen;"&gt;&lt;img title="image" style="display:inline;border-width:0px;border:0;" alt="image" src="http://i40.tinypic.com/16iijs.png" width="407" border="0" height="712" /&gt;&lt;/span&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;So, the example solution has a test fixture to test the purpose of the example. It was developed with NHibernate 2.1.0.2001.&lt;/p&gt;
&lt;p&gt;No more words, show me the code.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see the mapping files.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;Car.hbm.xml&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:411b4d59-2c28-4172-ab11-be3aabfc1650" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-mapping &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;urn:nhibernate-mapping-2.2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
                   assembly&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
                   namespace&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;class &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Car&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; table&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;cars&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;id &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Int64&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;generator &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;hilo&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;param &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;max_lo&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;50&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;param&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;generator&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;id&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;BrandName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;brand_name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModelName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;model_name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Kilometers&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;kilometers&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      
    &lt;/span&gt;&lt;span style="color:#008000;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="color:#008000;"&gt;audit attributes&lt;/span&gt;&lt;span style="color:#008000;"&gt;--&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;added_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;modified_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;    
    
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;erased_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;filter &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;avoidLogicalDeleted&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; condition&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;erased_date IS NULL&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;filter-def &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;avoidLogicalDeleted&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-mapping&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;It has the Id, 3 owned properties, and 9 properties for metadata auditing. The filter part is about logical deletes, we are going to talk about it in later. &lt;/p&gt;
&lt;p&gt;The &lt;b&gt;User.hbm.xml &lt;/b&gt;is really simple, we are not going to show it, it has no sense, anyway, the example solution can be downloaded.&lt;/p&gt;
&lt;p&gt;Now it&amp;rsquo;s time to show the NHibernate configuration file.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;hibernate.cfg.xml&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:3ba95b40-497a-4b28-8b49-14fc1742bf02" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-configuration  &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;urn:nhibernate-configuration-2.2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;session-factory&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;connection.driver_class&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;NHibernate.Driver.SqlClientDriver&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;connection.connection_string&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      Server=(local)\SQLEXPRESS;initial catalog=auditexample;Integrated Security=SSPI
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;adonet.batch_size&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;10&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;show_sql&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;false&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;dialect&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;NHibernate.Dialect.MsSql2005Dialect&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;query.substitutions&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;true 1, false 0, yes &amp;#39;Y&amp;#39;, no &amp;#39;N&amp;#39;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;proxyfactory.factory_class&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;mapping &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;assembly&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;listener &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.NHExtensions.CustomSaveUpdateEventListener, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;save-update&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;listener &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.NHExtensions.CustomDeleteEventListener, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;    
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;session-factory&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-configuration&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s analyze it, in the configuration file there is an attribute that is not so common, the listener attribute, as we mention before, with these attributes we are forcing NHibernate to lookup for the custom event listener that we inherited from the default listeners for ISession.Delete() and ISession.SaveUpdate() methods. Inside both class CustomSaveUpdateEventListener and CustomDeleteEventListener will appear a class called SecurityContext which handles the metada for auditing, this class will be discused later, after explaining both listeners.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;CustomSaveUpdateEventListener.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:e2d0d747-e26f-4d1c-a83b-59a459662651" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; CustomSaveUpdateEventListener : DefaultSaveOrUpdateEventListener
{
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; PerformSaveOrUpdate(SaveOrUpdateEvent evt)
   {
       var entity &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; evt.Entity &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;as&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditableEntity;

          &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (entity &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;){
              &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (entity.Id &lt;/span&gt;&lt;span style="color:#000000;"&gt;==&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
                  ProcessEntityForInserting(entity);
              &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;
                  ProcessEntityForUpdating(entity);
          }
       
          &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;base&lt;/span&gt;&lt;span style="color:#000000;"&gt;.PerformSaveOrUpdate(evt);
   }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;internal&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;virtual&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForInserting(AuditableEntity entity)
    {
       entity.AddedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;
       entity.AddedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       entity.AddedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();
       entity.AddedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();
    }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;internal&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;virtual&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForUpdating(AuditableEntity entity)
    {
       entity.ModifiedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;
       entity.ModifiedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       entity.ModifiedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();
       entity.ModifiedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();
    }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;h4&gt;&lt;b&gt;CustomDeleteEventListener.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:0d9f2bf9-3a0b-4402-832d-e0e844f30d37" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; CustomDeleteEventListener : DefaultDeleteEventListener
{
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; DeleteEntity(IEventSource session, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; entity,
                        NHibernate.Engine.EntityEntry entityEntry,
                        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color:#000000;"&gt; isCascadeDeleteEnabled,
                        NHibernate.Persister.Entity.IEntityPersister persister,
                        Iesi.Collections.ISet transientEntities)
   {
        var auditableEntity &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; entity &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;as&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditableEntity;

           &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (auditableEntity &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;){
              ProcessEntityForLogicalDelete(auditableEntity);
               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.CascadeBeforeDelete(session, persister, entity,
                   entityEntry, transientEntities);
               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.CascadeAfterDelete(session, persister, entity,
                   transientEntities);
       } &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt; {
            &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;normal delete&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;base&lt;/span&gt;&lt;span style="color:#000000;"&gt;.DeleteEntity(session, entity, entityEntry,
                isCascadeDeleteEnabled, persister, transientEntities);
       }
   }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForLogicalDelete(AuditableEntity entity)
   {
        entity.ErasedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;
        entity.ErasedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
        entity.ErasedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();
        entity.ErasedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();
   }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;h4&gt;&lt;b&gt;SecurityContext.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:64c46d35-180d-4eea-b740-092564076a3d" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; Ridiculous simple crosscut security class to get user credentials and audit metadata
&lt;/span&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color:#808080;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext
{
    &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;maybe System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString(), you decide&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; User LoggedUser {&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;;}

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; GetHostName()
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; Dns.GetHostName();
    }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; GetHostIP()
   {
        IPAddress[] addresses &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; Dns.GetHostAddresses(Dns.GetHostName());
        
        &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;be carefull and filter the public ip, use the local one
        &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;and of course, this has no sense for an httpcontext, use remote host ip instead&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (addresses.Length &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; addresses[&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;].ToString();
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
   }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;This class is just a simple helper to get the metadata needed for auditing, in this example it holds the session of the logged user too.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:a58b502c-190d-4d18-9988-4eed1524b883" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#000000;"&gt;[TestFixture]
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditTest
{
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; Configuration _configuration;
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; ISessionFactory _sessionFactory;

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; User _sampleUser1;
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; User _sampleUser2;

   [TestFixtureSetUp]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestFixtureSetUp()
   {
       XmlConfigurator.Configure();

       _configuration &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Configuration();
       _configuration.Configure();
       _sessionFactory &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _configuration.BuildSessionFactory();

       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;drop all tables on database&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;       _sessionFactory.OpenSession().CreateSQLQuery(
               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;IF OBJECT_ID (N&amp;#39;dbo.cars&amp;#39;, N&amp;#39;U&amp;#39;) IS NOT NULL DELETE cars&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        ).ExecuteUpdate();
       
       _sessionFactory.OpenSession().CreateSQLQuery(
               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;IF OBJECT_ID (N&amp;#39;dbo.users&amp;#39;, N&amp;#39;U&amp;#39;) IS NOT NULL DELETE users&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        ).ExecuteUpdate();
       
       _sessionFactory.OpenSession().CreateSQLQuery(
               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;EXEC sp_MSforeachtable ?&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        ).SetParameter(&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;,&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;DROP TABLE ?&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;).ExecuteUpdate();

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SchemaExport(_configuration).Create(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;false&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;true&lt;/span&gt;&lt;span style="color:#000000;"&gt;);

       PrepareLoggedUsers();
   }

   [TestFixtureTearDown]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestFixtureTearDown()
   {
       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;new SchemaExport(_configuration).Drop(false, true);&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;       _sessionFactory.Close();
   }

   [SetUp]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestSetUp()
   {
       _sessionFactory.OpenSession().CreateQuery(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;delete Car&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;).ExecuteUpdate();
   }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; PrepareLoggedUsers()
   {
       _sampleUser1 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; User() { Login &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;rcarlomagno&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Name &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Raul&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,
               LastName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Carlomagno&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Password &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;jijiji&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; };
       _sampleUser2 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; User() { Login &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ndaponte&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Name &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Nadia&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,
               LastName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Daponte&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Password &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;jujujuju&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; };

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.Save(_sampleUser1);
           session.Save(_sampleUser2);
           transaction.Commit();
       }

       SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sampleUser1;
   }

   [Test]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditAddedEntity()
   {
       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Renault&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Clio&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,
               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;110000&lt;/span&gt;&lt;span style="color:#000000;"&gt; };
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.AddedDate);
       Assert.IsNotNull(car.AddedBy);
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.AddedFromHostName));
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.AddedFromIP));
   }

   [Test]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditModifiedEntity()
   {
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Ford&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Ka&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;97544&lt;/span&gt;&lt;span style="color:#000000;"&gt;;

       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName,
               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers };

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.AddedDate);
       Assert.IsNotNull(car.AddedBy);


       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;let&amp;#39;s change logged user and wait 2 seconds to change the car&amp;#39;s data&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;       SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sampleUser2;
       Thread.Sleep(&lt;/span&gt;&lt;span style="color:#800080;"&gt;2000&lt;/span&gt;&lt;span style="color:#000000;"&gt;);

       car.Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;54000&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       car.ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Fiesta&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.ModifiedBy);
       Assert.IsNotNull(car.ModifiedDate);
       Assert.AreNotEqual(car.ModifiedDate, car.AddedDate);
       Assert.AreNotEqual(car.ModifiedBy, car.AddedBy);
       Assert.AreNotEqual(car.Kilometers, kilometers);
       Assert.AreNotEqual(car.ModelName, modelName);
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ModifiedFromHostName));
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ModifiedFromIP));
   }

   [Test]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditErasedEntity()
   {
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Citroen&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;C3&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;74665&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;

       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName,
               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers };

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;
       }

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.Delete(car);
           transaction.Commit();
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.ErasedBy);
       Assert.IsNotNull(car.ErasedDate);
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ErasedFromHostName));
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ErasedFromIP));

       ISession tmpSession &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession();
       tmpSession.EnableFilter(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;avoidLogicalDeleted&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
       Assert.AreEqual(&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;, tmpSession.CreateCriteria&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;().List().Count);
       tmpSession.DisableFilter(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;avoidLogicalDeleted&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
       Assert.AreEqual(&lt;/span&gt;&lt;span style="color:#800080;"&gt;1&lt;/span&gt;&lt;span style="color:#000000;"&gt;, tmpSession.CreateCriteria&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;().List().Count);

   }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;This test fixture proves that i am not lying. :-)&lt;/p&gt;
&lt;p&gt;A few last words, in CanAuditErasedEntity() method, at the end of it, it is supposed that if we deleted logically an entity, we don&amp;rsquo;t want to see it in the results, so before doing a Criteria or HQL to get some data, we must enable the filter on the ISession, because filters are disabled by default. I do not know if there is a way to enable it on the ISessionFactory, to avoid manually enable it each time we want to get some data.&lt;/p&gt;
&lt;p&gt;Well, this is the first time i write an article, i hope the next will be better. Sorry for my english.&lt;/p&gt;</description></item><item><title>Simple audit metadata and logical deletion of business entities</title><link>http://nhforge.org/wikis/howtonh/simple-audit-metadata-and-logical-deletion-of-business-entities/revision/1.aspx</link><pubDate>Sat, 20 Jun 2009 05:44:25 GMT</pubDate><guid isPermaLink="false">45f813f2-f1c4-4eda-a619-288e3cadc793:286</guid><dc:creator>Raul Carlomagno</dc:creator><comments>http://nhforge.org/wikis/howtonh/simple-audit-metadata-and-logical-deletion-of-business-entities/comments.aspx</comments><description>Revision 1 posted to How to by Raul Carlomagno on 20/06/2009 02:44:25 a.m.&lt;br /&gt;
&lt;p&gt;This article is just about a simple way to achieve auditing and perform logical delete of your sensible data, doing use of the listeners features of NHibernate. Design patterns and arquitecture principles are outside of the scope of the article, this is just an example, take it as a guide.&lt;/p&gt;
&lt;p&gt;Remember the old days when you had to audit data stored on your database, every time you build a query to insert, update or delete data, you had to &amp;ldquo;remember&amp;rdquo; to include the values for auditing (timestamp, user id). It was worse if you had stored procedures (by the way, i hate them) because suppose that was needed to take user credentials from another service to audit, you were limited by Transact-SQL language inside the stored procedure to access that service. Anyway, every time you build a query, you need those metadata values to store them, it could be good if you can centralize the place where you obtain and set those values (remember DRY).&lt;/p&gt;
&lt;p&gt;Maybe, in a strict way, auditing would take place in the business layer, but we are not going to miss this feature that NHibernate has for us, so auditing will take place in the data access layer. With NHibernate we can override its native methods when performing data access, NHibernate will fire events which we will have to override to audit the data and of course to do a logical deletion of our entities.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get inside the code and explain the domain. In the example we have a BaseEntity for any persistible entity, and then, for the auditable entities, the AuditableEntity which inherits from BaseEntity. We want to audit the cars inside the database. We will audit the date and time, the user, the IP address and the hostname for each action on the entity (insert, update, delete), i think this auditing metada is fine, you can add more of course, your fantasy is your limit.&lt;/p&gt;
&lt;p&gt;In fact this can&amp;rsquo;t be called audit, because we are not tracking changes of entities, just who did an action, when and from, pseudoaudit? [:D]&lt;/p&gt;
&lt;p&gt;&lt;a href="/wikis/howtonh/add.aspx/$image24.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="image" src="/wikis/howtonh/add.aspx/$image_thumb16.png" width="407" border="0" height="712" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;So, the example solution has a test fixture to test the purpose of the example. It was developed with NHibernate 2.1.0.2001.&lt;/p&gt;
&lt;p&gt;No more words, show me the code.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see the mapping files.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;Car.hbm.xml&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:411b4d59-2c28-4172-ab11-be3aabfc1650" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-mapping &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;urn:nhibernate-mapping-2.2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
                   assembly&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
                   namespace&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;class &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Car&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; table&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;cars&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;id &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Int64&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;generator &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;hilo&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;param &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;max_lo&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;50&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;param&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;generator&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;id&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;BrandName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;brand_name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModelName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;model_name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Kilometers&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;kilometers&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      
    &lt;/span&gt;&lt;span style="color:#008000;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="color:#008000;"&gt;audit attributes&lt;/span&gt;&lt;span style="color:#008000;"&gt;--&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;added_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AddedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;added_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;modified_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ModifiedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;modified_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;    
    
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;many-to-one &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedBy&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.Entities.User, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        column&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;erased_user_id&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; not-null&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedDate&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_date&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedFromIP&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_from_ip&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ErasedFromHostName&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; column &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;= &amp;quot;erased_from_hostname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;filter &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;avoidLogicalDeleted&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; condition&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;erased_date IS NULL&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;filter-def &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;avoidLogicalDeleted&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-mapping&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;It has the Id, 3 owned properties, and 9 properties for metadata auditing. The filter part is about logical deletes, we are going to talk about it in later. &lt;/p&gt;
&lt;p&gt;The &lt;b&gt;User.hbm.xml &lt;/b&gt;is really simple, we are not going to show it, it has no sense, anyway, the example solution can be downloaded.&lt;/p&gt;
&lt;p&gt;Now it&amp;rsquo;s time to show the NHibernate configuration file.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;hibernate.cfg.xml&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:3ba95b40-497a-4b28-8b49-14fc1742bf02" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-configuration  &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;urn:nhibernate-configuration-2.2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;session-factory&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;connection.driver_class&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;NHibernate.Driver.SqlClientDriver&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;connection.connection_string&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      Server=(local)\SQLEXPRESS;initial catalog=auditexample;Integrated Security=SSPI
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;adonet.batch_size&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;10&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;show_sql&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;false&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;dialect&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;NHibernate.Dialect.MsSql2005Dialect&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;query.substitutions&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;true 1, false 0, yes &amp;#39;Y&amp;#39;, no &amp;#39;N&amp;#39;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;proxyfactory.factory_class&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;mapping &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;assembly&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;listener &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.NHExtensions.CustomSaveUpdateEventListener, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;save-update&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;listener &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AuditExample.NHExtensions.CustomDeleteEventListener, AuditExample&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;
        type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;delete&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;    
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;session-factory&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate-configuration&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s analyze it, in the configuration file there is an attribute that is not so common, the listener attribute, as we mention before, with these attributes we are forcing NHibernate to lookup for the custom event listener that we inherited from the default listeners for ISession.Delete() and ISession.SaveUpdate() methods. Inside both class CustomSaveUpdateEventListener and CustomDeleteEventListener will appear a class called SecurityContext which handles the metada for auditing, this class will be discused later, after explaining both listeners.&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;CustomSaveUpdateEventListener.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:e2d0d747-e26f-4d1c-a83b-59a459662651" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; CustomSaveUpdateEventListener : DefaultSaveOrUpdateEventListener
{
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; PerformSaveOrUpdate(SaveOrUpdateEvent evt)
   {
       var entity &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; evt.Entity &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;as&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditableEntity;

          &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (entity &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;){
              &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (entity.Id &lt;/span&gt;&lt;span style="color:#000000;"&gt;==&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
                  ProcessEntityForInserting(entity);
              &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;
                  ProcessEntityForUpdating(entity);
          }
       
          &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;base&lt;/span&gt;&lt;span style="color:#000000;"&gt;.PerformSaveOrUpdate(evt);
   }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;internal&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;virtual&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForInserting(AuditableEntity entity)
    {
       entity.AddedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;
       entity.AddedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       entity.AddedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();
       entity.AddedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();
    }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;internal&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;virtual&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForUpdating(AuditableEntity entity)
    {
       entity.ModifiedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;
       entity.ModifiedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       entity.ModifiedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();
       entity.ModifiedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();
    }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;h4&gt;&lt;b&gt;CustomDeleteEventListener.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:0d9f2bf9-3a0b-4402-832d-e0e844f30d37" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; CustomDeleteEventListener : DefaultDeleteEventListener
{
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; DeleteEntity(IEventSource session, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; entity,
                        NHibernate.Engine.EntityEntry entityEntry,
                        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color:#000000;"&gt; isCascadeDeleteEnabled,
                        NHibernate.Persister.Entity.IEntityPersister persister,
                        Iesi.Collections.ISet transientEntities)
   {
        var auditableEntity &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; entity &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;as&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditableEntity;

           &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (auditableEntity &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;){
              ProcessEntityForLogicalDelete(auditableEntity);
               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.CascadeBeforeDelete(session, persister, entity,
                   entityEntry, transientEntities);
               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.CascadeAfterDelete(session, persister, entity,
                   transientEntities);
       } &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt; {
            &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;normal delete&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;               &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;base&lt;/span&gt;&lt;span style="color:#000000;"&gt;.DeleteEntity(session, entity, entityEntry,
                isCascadeDeleteEnabled, persister, transientEntities);
       }
   }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessEntityForLogicalDelete(AuditableEntity entity)
   {
        entity.ErasedDate &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; DateTime.Now;
        entity.ErasedBy &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;??&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
        entity.ErasedFromIP &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostIP();
        entity.ErasedFromHostName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext.GetHostName();
   }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;h4&gt;&lt;b&gt;SecurityContext.cs&lt;/b&gt;&lt;/h4&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:64c46d35-180d-4eea-b740-092564076a3d" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; Ridiculous simple crosscut security class to get user credentials and audit metadata
&lt;/span&gt;&lt;span style="color:#808080;"&gt;///&lt;/span&gt;&lt;span style="color:#008000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color:#808080;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; SecurityContext
{
    &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;maybe System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString(), you decide&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; User LoggedUser {&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;;}

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; GetHostName()
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; Dns.GetHostName();
    }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; GetHostIP()
   {
        IPAddress[] addresses &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; Dns.GetHostAddresses(Dns.GetHostName());
        
        &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;be carefull and filter the public ip, use the local one
        &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;and of course, this has no sense for an httpcontext, use remote host ip instead&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (addresses.Length &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; addresses[&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;].ToString();
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
   }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;This class is just a simple helper to get the metadata needed for auditing, in this example it holds the session of the logged user too.&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:a58b502c-190d-4d18-9988-4eed1524b883" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;overflow:auto;"&gt;&lt;span style="color:#000000;"&gt;[TestFixture]
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; AuditTest
{
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; Configuration _configuration;
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; ISessionFactory _sessionFactory;

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; User _sampleUser1;
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; User _sampleUser2;

   [TestFixtureSetUp]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestFixtureSetUp()
   {
       XmlConfigurator.Configure();

       _configuration &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Configuration();
       _configuration.Configure();
       _sessionFactory &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _configuration.BuildSessionFactory();

       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;drop all tables on database&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;       _sessionFactory.OpenSession().CreateSQLQuery(
               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;IF OBJECT_ID (N&amp;#39;dbo.cars&amp;#39;, N&amp;#39;U&amp;#39;) IS NOT NULL DELETE cars&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        ).ExecuteUpdate();
       
       _sessionFactory.OpenSession().CreateSQLQuery(
               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;IF OBJECT_ID (N&amp;#39;dbo.users&amp;#39;, N&amp;#39;U&amp;#39;) IS NOT NULL DELETE users&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        ).ExecuteUpdate();
       
       _sessionFactory.OpenSession().CreateSQLQuery(
               &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;EXEC sp_MSforeachtable ?&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        ).SetParameter(&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;,&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;DROP TABLE ?&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;).ExecuteUpdate();

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SchemaExport(_configuration).Create(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;false&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;true&lt;/span&gt;&lt;span style="color:#000000;"&gt;);

       PrepareLoggedUsers();
   }

   [TestFixtureTearDown]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestFixtureTearDown()
   {
       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;new SchemaExport(_configuration).Drop(false, true);&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;       _sessionFactory.Close();
   }

   [SetUp]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; TestSetUp()
   {
       _sessionFactory.OpenSession().CreateQuery(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;delete Car&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;).ExecuteUpdate();
   }

   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; PrepareLoggedUsers()
   {
       _sampleUser1 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; User() { Login &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;rcarlomagno&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Name &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Raul&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,
               LastName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Carlomagno&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Password &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;jijiji&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; };
       _sampleUser2 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; User() { Login &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ndaponte&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Name &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Nadia&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,
               LastName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Daponte&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Password &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;jujujuju&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; };

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.Save(_sampleUser1);
           session.Save(_sampleUser2);
           transaction.Commit();
       }

       SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sampleUser1;
   }

   [Test]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditAddedEntity()
   {
       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Renault&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Clio&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,
               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;110000&lt;/span&gt;&lt;span style="color:#000000;"&gt; };
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.AddedDate);
       Assert.IsNotNull(car.AddedBy);
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.AddedFromHostName));
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.AddedFromIP));
   }

   [Test]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditModifiedEntity()
   {
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Ford&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Ka&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;97544&lt;/span&gt;&lt;span style="color:#000000;"&gt;;

       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName,
               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers };

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.AddedDate);
       Assert.IsNotNull(car.AddedBy);


       &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;let&amp;#39;s change logged user and wait 2 seconds to change the car&amp;#39;s data&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;       SecurityContext.LoggedUser &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sampleUser2;
       Thread.Sleep(&lt;/span&gt;&lt;span style="color:#800080;"&gt;2000&lt;/span&gt;&lt;span style="color:#000000;"&gt;);

       car.Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;54000&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       car.ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Fiesta&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.ModifiedBy);
       Assert.IsNotNull(car.ModifiedDate);
       Assert.AreNotEqual(car.ModifiedDate, car.AddedDate);
       Assert.AreNotEqual(car.ModifiedBy, car.AddedBy);
       Assert.AreNotEqual(car.Kilometers, kilometers);
       Assert.AreNotEqual(car.ModelName, modelName);
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ModifiedFromHostName));
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ModifiedFromIP));
   }

   [Test]
   &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanAuditErasedEntity()
   {
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Citroen&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;C3&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;const&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;74665&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;long&lt;/span&gt;&lt;span style="color:#000000;"&gt; carId;

       Car car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Car() { BrandName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; brandName, ModelName &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; modelName,
               Kilometers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; kilometers };

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.SaveOrUpdate(car);
           transaction.Commit();
           carId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; car.Id;
       }

       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ISession session &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession())
       &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; (ITransaction transaction &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; session.BeginTransaction())
       {
           session.Delete(car);
           transaction.Commit();
       }

       car &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession().Get&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(carId);

       Assert.IsNotNull(car);
       Assert.IsNotNull(car.ErasedBy);
       Assert.IsNotNull(car.ErasedDate);
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ErasedFromHostName));
       Assert.IsFalse(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;.IsNullOrEmpty(car.ErasedFromIP));

       ISession tmpSession &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _sessionFactory.OpenSession();
       tmpSession.EnableFilter(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;avoidLogicalDeleted&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
       Assert.AreEqual(&lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;, tmpSession.CreateCriteria&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;().List().Count);
       tmpSession.DisableFilter(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;avoidLogicalDeleted&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
       Assert.AreEqual(&lt;/span&gt;&lt;span style="color:#800080;"&gt;1&lt;/span&gt;&lt;span style="color:#000000;"&gt;, tmpSession.CreateCriteria&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;().List().Count);

   }
}&lt;/span&gt;&lt;/pre&gt;
&amp;lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&amp;gt;&lt;/div&gt;
&lt;p&gt;This test fixture proves that i am not lying. :-)&lt;/p&gt;
&lt;p&gt;A few last words, in CanAuditErasedEntity() method, at the end of it, it is supposed that if we deleted logically an entity, we don&amp;rsquo;t want to see it in the results, so before doing a Criteria or HQL to get some data, we must enable the filter on the ISession, because filters are disabled by default. I do not know if there is a way to enable it on the ISessionFactory, to avoid manually enable it each time we want to get some data.&lt;/p&gt;
&lt;p&gt;Well, this is the first time i write an article, i hope the next will be better. Sorry for my english.&lt;/p&gt;</description></item></channel></rss>
