Contextual data using NHibernate filtershttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters.aspxQuick starts, tutorials, code snippets, custom user types, application blocks and more...en-USCommunityServer 2008.5 SP1 (Build: 31106.3070)Contextual data using NHibernate filtershttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters.aspxFri, 13 Feb 2009 14:32:03 GMT45f813f2-f1c4-4eda-a619-288e3cadc793:48Germán Schuagerhttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters/comments.aspxCurrent revision posted to How to by Germán Schuager on 13/02/2009 11:32:03 a.m.<br /> <h2>Contextual data using NHibernate filters</h2> <div style="font-size: 90%;">Filed under: <span style="background: SpringGreen;">Filters</span><span style="background: SpringGreen;">,</span> <span style="background: SpringGreen;">Interceptor</span></div> <p>I&#39;m in the middle of the development process of an application using NH for data access, and I&#39;m faced with a requirement that could be stated as follows:</p> <blockquote><i>The application needs to provide support for different Contexts of execution, and certain entities must be context-aware, which means that at a given time, the application only sees instances of these entities that correspond to the current context of execution.</i></blockquote> <p>Now, just remember that I have several entities defined that are used throught the entire application layer stack, so I wanted to solve this issue modifying as little as possible.<br /><br />I&#39;m very proud with the solution that I came up with, and also very amazed by the power of NHibernate.<br /><br />To simplify a little lets assume that I have a static class that defines the current context of execution:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public enum ContexType<br />{<br /> ContextA,<br /> ContextB,<br />}<br />public static class Context<br />{<br /> public static ContextType Current { get; set; }<br />}<br /></pre> <p> Then, I create an interface that will be implemented by all the entities that need to be contextualized:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public interface IcontextAware<br />{<br /> ContextType Context { get; set; }<br />}<br /></pre> <p> Given a Cat class that needs to be contextualized, then I add the property to the class and to the mapping:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public class Cat : Entity, IcontextAware<br />{<br /> ...<br /> ContextType Context { get; set; }<br /> ...<br />}</pre> &nbsp; <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&lt;class name=&quot;Cat&quot;&gt;<br /> ...<br /> &lt;property name=&quot;Context&quot;&gt;<br /> ...<br />&lt;/class&gt;<br /></pre> <p> The idea now, is to use the dynamic filtering capabilities of NHibernate to only retrieve the Cats instances corresponding with the current context every time that a query against Cat is issued.<br />Typically this means that I need to add a filter definition to the mappings and the specify the condition for that filter in every class mapping that need to be aware of this behavior.<br />But there is an easier way to do this automatically:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">var filterParametersType = new Dictionary&lt;string, Itype&gt;(1);<br />filterParametersType.Add(&quot;current&quot;, NhibernateUtil.Enum(typeof(ContextType)));<br />cfg.AddFilterDefinition(new FilterDefinition(&quot;contextFilter&quot;, &quot;:current = Context&quot;, filterParametersType));<br /><br />foreach (var mapping in cfg.ClassMappings)<br />{<br /> if (typeof(IContextAware).IsAssignableFrom(mapping.MappedClass))<br /> {<br /> mapping.AddFilter(&quot;contextFilter&quot;, &quot;:current = Context&quot;);<br /> }<br />}<br /></pre> <p> Just do this (cfg is the NH Configuration object) before building the session factory and it creates the correct filter definition and adds the condition to every entity mapped that implements IContextAware.<br /><br />At this point we just have our filter defined; now we need to enable it in order to actually filter something. It would be very handy if we can enable filtering at session factory scope, but since the session factory is immutable we need to enable it for each session that we will be using.<br /><br />Wait.... maybe something else can do this work for us...<br /><br />The following interceptor actually takes care of 2 things:<br />1. enables the context filter as soon as it is attached to the session, and<br />2. assigns the correct value to the Context property of entities implementing IContextAware when they are persisted.</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public class ContextInterceptor : EmptyInterceptor<br />{<br /> public override void SetSession(ISession session)<br /> {<br /> session.EnableFilter(&quot;contextFilter&quot;).SetParameter(&quot;current&quot;, Context.Current);<br /> }<br /><br /> public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)<br /> {<br /> var contextAware = entity as IContextAware;<br /> if (contextAware != null)<br /> {<br /> int index = Array.Find(propertyNames, 0, x =&gt; x.Equals(&quot;Context&quot;));<br /> state[index] = contextAware.Context = Context.Current;<br /> return true;<br /> }<br /> return false;<br /> }<br />}<br /></pre> <p> Every session in the application needs to be created specifying this interceptor, but this should be an easy change (that depends on your architecture) if you are doing things right.<br /><br />And thats all, the rest of the application is untouched and the requirement is fulfilled in a very elegant way. </p> <p>(the original article is <a href="http://blog.schuager.com/2009/02/contextual-data-using-nhibernate.html">here</a>)</p>Contextual data using NHibernate filtershttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters/revision/4.aspxFri, 13 Feb 2009 14:32:03 GMT45f813f2-f1c4-4eda-a619-288e3cadc793:222Germán Schuagerhttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters/comments.aspxRevision 4 posted to How to by Germán Schuager on 13/02/2009 11:32:03 a.m.<br /> <h2>Contextual data using NHibernate filters</h2> <p>I&#39;m in the middle of the development process of an application using NH for data access, and I&#39;m faced with a requirement that could be stated as follows:</p> <blockquote><i>The application needs to provide support for different Contexts of execution, and certain entities must be context-aware, which means that at a given time, the application only sees instances of these entities that correspond to the current context of execution.</i></blockquote> <p>Now, just remember that I have several entities defined that are used throught the entire application layer stack, so I wanted to solve this issue modifying as little as possible.<br /><br />I&#39;m very proud with the solution that I came up with, and also very amazed by the power of NHibernate.<br /><br />To simplify a little lets assume that I have a static class that defines the current context of execution:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public enum ContexType<br />{<br /> ContextA,<br /> ContextB,<br />}<br />public static class Context<br />{<br /> public static ContextType Current { get; set; }<br />}<br /></pre> <p> Then, I create an interface that will be implemented by all the entities that need to be contextualized:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public interface IcontextAware<br />{<br /> ContextType Context { get; set; }<br />}<br /></pre> <p> Given a Cat class that needs to be contextualized, then I add the property to the class and to the mapping:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public class Cat : Entity, IcontextAware<br />{<br /> ...<br /> ContextType Context { get; set; }<br /> ...<br />}</pre> &nbsp; <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&lt;class name=&quot;Cat&quot;&gt;<br /> ...<br /> &lt;property name=&quot;Context&quot;&gt;<br /> ...<br />&lt;/class&gt;<br /></pre> <p> The idea now, is to use the dynamic filtering capabilities of NHibernate to only retrieve the Cats instances corresponding with the current context every time that a query against Cat is issued.<br />Typically this means that I need to add a filter definition to the mappings and the specify the condition for that filter in every class mapping that need to be aware of this behavior.<br />But there is an easier way to do this automatically:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">var filterParametersType = new Dictionary&lt;string, Itype&gt;(1);<br />filterParametersType.Add(&quot;current&quot;, NhibernateUtil.Enum(typeof(ContextType)));<br />cfg.AddFilterDefinition(new FilterDefinition(&quot;contextFilter&quot;, &quot;:current = Context&quot;, filterParametersType));<br /><br />foreach (var mapping in cfg.ClassMappings)<br />{<br /> if (typeof(IContextAware).IsAssignableFrom(mapping.MappedClass))<br /> {<br /> mapping.AddFilter(&quot;contextFilter&quot;, &quot;:current = Context&quot;);<br /> }<br />}<br /></pre> <p> Just do this (cfg is the NH Configuration object) before building the session factory and it creates the correct filter definition and adds the condition to every entity mapped that implements IContextAware.<br /><br />At this point we just have our filter defined; now we need to enable it in order to actually filter something. It would be very handy if we can enable filtering at session factory scope, but since the session factory is immutable we need to enable it for each session that we will be using.<br /><br />Wait.... maybe something else can do this work for us...<br /><br />The following interceptor actually takes care of 2 things:<br />1. enables the context filter as soon as it is attached to the session, and<br />2. assigns the correct value to the Context property of entities implementing IContextAware when they are persisted.</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public class ContextInterceptor : EmptyInterceptor<br />{<br /> public override void SetSession(ISession session)<br /> {<br /> session.EnableFilter(&quot;contextFilter&quot;).SetParameter(&quot;current&quot;, Context.Current);<br /> }<br /><br /> public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)<br /> {<br /> var contextAware = entity as IContextAware;<br /> if (contextAware != null)<br /> {<br /> <span style="background: SpringGreen;">int</span> <span style="background: SpringGreen;">index</span> <span style="background: SpringGreen;">=</span> <span style="background: SpringGreen;">Array.Find(propertyNames</span><span style="background: SpringGreen;">,</span> <span style="background: SpringGreen;">0</span><span style="background: SpringGreen;">,</span> <span style="background: SpringGreen;">x</span> <span style="background: SpringGreen;">=</span><span style="background: SpringGreen;">&gt;</span> <span style="background: SpringGreen;">x.Equals</span><span style="background: SpringGreen;">(</span><span style="background: SpringGreen;">&quot;Context&quot;));</span><br /> <span style="background: SpringGreen;">state[index</span><span style="background: SpringGreen;">]</span> <span style="background: SpringGreen;">=</span> contextAware.Context = Context.Current;<br /> return true;<br /> }<br /> return false;<br /> }<br />}<br /></pre> <p> Every session in the application needs to be created specifying this interceptor, but this should be an easy change (that depends on your architecture) if you are doing things right.<br /><br />And thats all, the rest of the application is untouched and the requirement is fulfilled in a very elegant way. </p> <p>(the original article is <a href="http://blog.schuager.com/2009/02/contextual-data-using-nhibernate.html">here</a>)</p>Contextual data using NHibernate filtershttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters/revision/3.aspxThu, 12 Feb 2009 20:25:48 GMT45f813f2-f1c4-4eda-a619-288e3cadc793:221Germán Schuagerhttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters/comments.aspxRevision 3 posted to How to by Germán Schuager on 12/02/2009 05:25:48 p.m.<br /> <h2>Contextual data using NHibernate filters</h2> <p>I&#39;m in the middle of the development process of an application using NH for data access, and I&#39;m faced with a requirement that could be stated as follows:</p> <blockquote><i>The application needs to provide support for different Contexts of execution, and certain entities must be context-aware, which means that at a given time, the application only sees instances of these entities that correspond to the current context of execution.</i></blockquote> <p>Now, just remember that I have several entities defined that are used throught the entire application layer stack, so I wanted to solve this issue modifying as little as possible.<br /><br />I&#39;m very proud with the solution that I came up with, and also very amazed by the power of NHibernate.<br /><br />To simplify a little lets assume that I have a static class that defines the current context of execution:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public enum ContexType { ContextA, ContextB, } public static class Context { public static ContextType Current { get; set; } } </pre> <p> Then, I create an interface that will be implemented by all the entities that need to be contextualized:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public interface IcontextAware<br />{ ContextType Context { get; set; } } </pre> <p> Given a Cat class that needs to be contextualized, then I add the property to the class and to the mapping:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public class Cat : Entity, IcontextAware<br />{ ... ContextType Context { get; set; } ... }</pre> &nbsp; <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&lt;class name=&quot;Cat&quot;&gt; ... &lt;property name=&quot;Context&quot;&gt; ... &lt;/class&gt; </pre> <p> The idea now, is to use the dynamic filtering capabilities of NHibernate to only retrieve the Cats instances corresponding with the current context every time that a query against Cat is issued.<br />Typically this means that I need to add a filter definition to the mappings and the specify the condition for that filter in every class mapping that need to be aware of this behavior.<br />But there is an easier way to do this automatically:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">var filterParametersType = new Dictionary&lt;string, Itype&gt;(1); filterParametersType.Add(&quot;current&quot;, NhibernateUtil.Enum(typeof(ContextType))); cfg.AddFilterDefinition(new FilterDefinition(&quot;contextFilter&quot;, &quot;:current = Context&quot;, filterParametersType)); foreach (var mapping in cfg.ClassMappings) { if (typeof(IContextAware).IsAssignableFrom(mapping.MappedClass)) { mapping.AddFilter(&quot;contextFilter&quot;, &quot;:current = Context&quot;); } } </pre> <p> Just do this (cfg is the NH Configuration object) before building the session factory and it creates the correct filter definition and adds the condition to every entity mapped that implements IContextAware.<br /><br />At this point we just have our filter defined; now we need to enable it in order to actually filter something. It would be very handy if we can enable filtering at session factory scope, but since the session factory is immutable we need to enable it for each session that we will be using.<br /><br />Wait.... maybe something else can do this work for us...<br /><br />The following interceptor actually takes care of 2 things:<br />1. enables the context filter as soon as it is attached to the session, and<br />2. assigns the correct value to the Context property of entities implementing IContextAware when they are persisted.</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public class ContextInterceptor : EmptyInterceptor { public override void SetSession(ISession session) { session.EnableFilter(&quot;contextFilter&quot;).SetParameter(&quot;current&quot;, Context.Current); } public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types) { var contextAware = entity as <span style="text-decoration: line-through; color: red;">IcontextAware</span><span style="background: SpringGreen;">IContextAware</span>; if (contextAware != null) { contextAware.Context = Context.Current; return true; } return false; } } </pre> <p> Every session in the application needs to be created specifying this interceptor, but this should be an easy change (that depends on your architecture) if you are doing things right.<br /><br />And thats all, the rest of the application is untouched and the requirement is fulfilled in a very elegant way. </p> <p>(the original article is <a href="http://blog.schuager.com/2009/02/contextual-data-using-nhibernate.html">here</a>)</p>Contextual data using NHibernate filtershttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters/revision/2.aspxThu, 12 Feb 2009 20:23:31 GMT45f813f2-f1c4-4eda-a619-288e3cadc793:220Germán Schuagerhttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters/comments.aspxRevision 2 posted to How to by Germán Schuager on 12/02/2009 05:23:31 p.m.<br /> <h2>Contextual data using NHibernate filters</h2> <p> <span style="text-decoration: line-through; color: red;">&lt;meta</span> <span style="text-decoration: line-through; color: red;">http-equiv=</span><span style="text-decoration: line-through; color: red;">&quot;CONTENT-TYPE&quot;</span> <span style="text-decoration: line-through; color: red;">content=</span><span style="text-decoration: line-through; color: red;">&quot;text/html;</span> <span style="text-decoration: line-through; color: red;">charset=utf-8</span><span style="text-decoration: line-through; color: red;">&quot;</span> <span style="text-decoration: line-through; color: red;">/</span><span style="text-decoration: line-through; color: red;">&gt;</span> <span style="text-decoration: line-through; color: red;">&lt;title&gt;&lt;/title&gt;</span> <span style="text-decoration: line-through; color: red;">&lt;meta</span> <span style="text-decoration: line-through; color: red;">name=</span><span style="text-decoration: line-through; color: red;">&quot;GENERATOR&quot;</span> <span style="text-decoration: line-through; color: red;">content=</span><span style="text-decoration: line-through; color: red;">&quot;OpenOffice.org</span> <span style="text-decoration: line-through; color: red;">3.0</span> <span style="text-decoration: line-through; color: red;">(</span><span style="text-decoration: line-through; color: red;">Win32)</span><span style="text-decoration: line-through; color: red;">&quot;</span> <span style="text-decoration: line-through; color: red;">/</span><span style="text-decoration: line-through; color: red;">&gt;</span> <span style="text-decoration: line-through; color: red;">&lt;style</span> <span style="text-decoration: line-through; color: red;">type=</span><span style="text-decoration: line-through; color: red;">&quot;text/css&quot;&gt;&lt;!--</span> <span style="text-decoration: line-through; color: red;">-</span><span style="text-decoration: line-through; color: red;">-</span><span style="text-decoration: line-through; color: red;">&gt;&lt;/style&gt;</span> <p>I&#39;m in the middle of the development process of an application using NH for data access, and I&#39;m faced with a requirement that could be stated as follows:</p> <blockquote><i>The application needs to provide support for different Contexts of execution, and certain entities must be context-aware, which means that at a given time, the application only sees instances of these entities that correspond to the current context of execution.</i></blockquote> <p>Now, just remember that I have several entities defined that are used throught the entire application layer stack, so I wanted to solve this issue modifying as little as possible.<br /><br />I&#39;m very proud with the solution that I came up with, and also very amazed by the power of NHibernate.<br /><br />To simplify a little lets assume that I have a static class that defines the current context of execution:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public enum ContexType { ContextA, ContextB, } public static class Context { public static ContextType Current { get; set; } } </pre> <p> Then, I create an interface that will be implemented by all the entities that need to be contextualized:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public interface IcontextAware<br />{ ContextType Context { get; set; } } </pre> <p> Given a Cat class that needs to be contextualized, then I add the property to the class and to the mapping:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public class Cat : Entity, IcontextAware<br />{ ... ContextType Context { get; set; } ... } &lt;class name=&quot;Cat&quot;&gt; ... &lt;property name=&quot;Context&quot;&gt; ... &lt;/class&gt; </pre> <p> The idea now, is to use the dynamic filtering capabilities of NHibernate to only retrieve the Cats instances corresponding with the current context every time that a query against Cat is issued.<br />Typically this means that I need to add a filter definition to the mappings and the specify the condition for that filter in every class mapping that need to be aware of this behavior.<br />But there is an easier way to do this automatically:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">var filterParametersType = new Dictionary&lt;string, Itype&gt;(1); filterParametersType.Add(&quot;current&quot;, NhibernateUtil.Enum(typeof(ContextType))); cfg.AddFilterDefinition(new FilterDefinition(&quot;contextFilter&quot;, &quot;:current = Context&quot;, filterParametersType)); foreach (var mapping in cfg.ClassMappings) { if (typeof(IContextAware).IsAssignableFrom(mapping.MappedClass)) { mapping.AddFilter(&quot;contextFilter&quot;, &quot;:current = Context&quot;); } } </pre> <p> Just do this (cfg is the NH Configuration object) before building the session factory and it creates the correct filter definition and adds the condition to every entity mapped that implements IContextAware.<br /><br />At this point we just have our filter defined; now we need to enable it in order to actually filter something. It would be very handy if we can enable filtering at session factory scope, but since the session factory is immutable we need to enable it for each session that we will be using.<br /><br />Wait.... maybe something else can do this work for us...<br /><br />The following interceptor actually takes care of 2 things:<br />1. enables the context filter as soon as it is attached to the session, and<br />2. assigns the correct value to the Context property of entities implementing IContextAware when they are persisted.</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public class ContextInterceptor : EmptyInterceptor { public override void SetSession(ISession session) { session.EnableFilter(&quot;contextFilter&quot;).SetParameter(&quot;current&quot;, Context.Current); } public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types) { var contextAware = entity as IcontextAware; if (contextAware != null) { contextAware.Context = Context.Current; return true; } return false; } } </pre> <p> Every session in the application needs to be created specifying this interceptor, but this should be an easy change (that depends on your architecture) if you are doing things right.<br /><br />And thats all, the rest of the application is untouched and the requirement is fulfilled in a very elegant way. </p> <p>(the original article is <a href="http://blog.schuager.com/2009/02/contextual-data-using-nhibernate.html">here</a>)</p>Contextual data using NHibernate filtershttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters/revision/1.aspxThu, 12 Feb 2009 20:22:50 GMT45f813f2-f1c4-4eda-a619-288e3cadc793:219Germán Schuagerhttp://nhforge.org/wikis/howtonh/contextual-data-using-nhibernate-filters/comments.aspxRevision 1 posted to How to by Germán Schuager on 12/02/2009 05:22:50 p.m.<br /> <p> &lt;meta http-equiv=&quot;CONTENT-TYPE&quot; content=&quot;text/html; charset=utf-8&quot; /&gt; &lt;title&gt;&lt;/title&gt; &lt;meta name=&quot;GENERATOR&quot; content=&quot;OpenOffice.org 3.0 (Win32)&quot; /&gt; &lt;style type=&quot;text/css&quot;&gt;&lt;!-- --&gt;&lt;/style&gt; </p> <p>I&#39;m in the middle of the development process of an application using NH for data access, and I&#39;m faced with a requirement that could be stated as follows:</p> <blockquote>The application needs to provide support for different Contexts of execution, and certain entities must be context-aware, which means that at a given time, the application only sees instances of these entities that correspond to the current context of execution.</blockquote> <p>Now, just remember that I have several entities defined that are used throught the entire application layer stack, so I wanted to solve this issue modifying as little as possible.<br /><br />I&#39;m very proud with the solution that I came up with, and also very amazed by the power of NHibernate.<br /><br />To simplify a little lets assume that I have a static class that defines the current context of execution:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public enum ContexType { ContextA, ContextB, } public static class Context { public static ContextType Current { get; set; } } </pre> <p> Then, I create an interface that will be implemented by all the entities that need to be contextualized:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public interface IcontextAware<br />{ ContextType Context { get; set; } } </pre> <p> Given a Cat class that needs to be contextualized, then I add the property to the class and to the mapping:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public class Cat : Entity, IcontextAware<br />{ ... ContextType Context { get; set; } ... } &lt;class name=&quot;Cat&quot;&gt; ... &lt;property name=&quot;Context&quot;&gt; ... &lt;/class&gt; </pre> <p> The idea now, is to use the dynamic filtering capabilities of NHibernate to only retrieve the Cats instances corresponding with the current context every time that a query against Cat is issued.<br />Typically this means that I need to add a filter definition to the mappings and the specify the condition for that filter in every class mapping that need to be aware of this behavior.<br />But there is an easier way to do this automatically:</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">var filterParametersType = new Dictionary&lt;string, Itype&gt;(1); filterParametersType.Add(&quot;current&quot;, NhibernateUtil.Enum(typeof(ContextType))); cfg.AddFilterDefinition(new FilterDefinition(&quot;contextFilter&quot;, &quot;:current = Context&quot;, filterParametersType)); foreach (var mapping in cfg.ClassMappings) { if (typeof(IContextAware).IsAssignableFrom(mapping.MappedClass)) { mapping.AddFilter(&quot;contextFilter&quot;, &quot;:current = Context&quot;); } } </pre> <p> Just do this (cfg is the NH Configuration object) before building the session factory and it creates the correct filter definition and adds the condition to every entity mapped that implements IContextAware.<br /><br />At this point we just have our filter defined; now we need to enable it in order to actually filter something. It would be very handy if we can enable filtering at session factory scope, but since the session factory is immutable we need to enable it for each session that we will be using.<br /><br />Wait.... maybe something else can do this work for us...<br /><br />The following interceptor actually takes care of 2 things:<br />1. enables the context filter as soon as it is attached to the session, and<br />2. assigns the correct value to the Context property of entities implementing IContextAware when they are persisted.</p> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">public class ContextInterceptor : EmptyInterceptor { public override void SetSession(ISession session) { session.EnableFilter(&quot;contextFilter&quot;).SetParameter(&quot;current&quot;, Context.Current); } public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types) { var contextAware = entity as IcontextAware; if (contextAware != null) { contextAware.Context = Context.Current; return true; } return false; } } </pre> <p> Every session in the application needs to be created specifying this interceptor, but this should be an easy change (that depends on your architecture) if you are doing things right.<br /><br />And thats all, the rest of the application is untouched and the requirement is fulfilled in a very elegant way. </p> <p>(the original article is <a href="http://blog.schuager.com/2009/02/contextual-data-using-nhibernate.html">here</a>)</p>