<?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>Customizing Fluent Nhibernate's AutoPersistenceModel Conventions</title><link>http://nhforge.org/wikis/howtonh/customizing-fluent-nhibernate-s-autopersistencemodel-conventions.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>Customizing Fluent Nhibernate's AutoPersistenceModel Conventions</title><link>http://nhforge.org/wikis/howtonh/customizing-fluent-nhibernate-s-autopersistencemodel-conventions.aspx</link><pubDate>Fri, 25 Dec 2009 17:04:15 GMT</pubDate><guid isPermaLink="false">45f813f2-f1c4-4eda-a619-288e3cadc793:69</guid><dc:creator>Chris Nicola</dc:creator><comments>http://nhforge.org/wikis/howtonh/customizing-fluent-nhibernate-s-autopersistencemodel-conventions/comments.aspx</comments><description>Current revision posted to How to by Chris Nicola on 25/12/2009 02:04:15 p.m.&lt;br /&gt;
&lt;h2&gt;Customizing Fluent Nhibernate&amp;#39;s AutoPersistenceModel Conventions&lt;/h2&gt;
&lt;div style="font-size: 90%;"&gt;Filed under: &lt;span style="text-decoration: line-through; color: red;"&gt;Mapping&lt;/span&gt;&lt;span style="text-decoration: line-through; color: red;"&gt;,&lt;/span&gt; &lt;span style="text-decoration: line-through; color: red;"&gt;FluentNH&lt;/span&gt;&lt;span style="text-decoration: line-through; color: red;"&gt;,&lt;/span&gt; AutoPersistenceModel, convention over configuration&lt;span style="background: SpringGreen;"&gt;,&lt;/span&gt; &lt;span style="background: SpringGreen;"&gt;FluentNH&lt;/span&gt;&lt;span style="background: SpringGreen;"&gt;,&lt;/span&gt; &lt;span style="background: SpringGreen;"&gt;Mapping&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="http://www.lucisferre.net/image.axd?picture=xmlschool_1.jpg"&gt;&lt;img style="border-bottom:0px;border-left:0px;margin:0px 6px 0px 0px;display:inline;border-top:0px;border-right:0px;" title="xmlschool" src="http://www.lucisferre.net/image.axd?picture=xmlschool_thumb.jpg" alt="xmlschool" align="left" border="0" width="184" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(this was originally blogged about &lt;a href="http://www.lucisferre.net/post.aspx?id=0c0eb379-f939-406b-bfb9-a1130a5be664"&gt;here&lt;/a&gt;) &lt;/p&gt;
&lt;p&gt;One of the things I get a fair bit of use out of is the fluent nHibernate project and the AutoPersistenceModel.&amp;nbsp; If you are not very familiar with fluentNH or AutoPersistenceModel then I would suggest checking out their &lt;a href="http://wiki.fluentnhibernate.org/Main_Page"&gt;wiki&lt;/a&gt;, as what I am about to discuss, while not difficult, is some relatively advanced usage.&lt;/p&gt;
&lt;p&gt;The purpose of AutoPersistenceModel is to automatically generate the nHibernate configuration (the HBM files if you are currently used to XML configuration) directly from your model based on Convention over Configuration, &lt;a href="http://www.jameskovacs.com/blog/NETRocks475JamesKovacsOnConventionoverConfiguration.aspx"&gt;you can hear James Kovacs discuss this concept on .NET Rocks&lt;/a&gt;.&amp;nbsp; With tools like SchemaExport and SchemaUpdate it is even possible to automatically generate and execute DDL scripts against your database to keep the schema in sync with your model.&amp;nbsp; This can be a bit rails like in it&amp;#39;s use, in fact &lt;a href="http://adventuresinagile.blogspot.com/"&gt;Adam Dymitruk&lt;/a&gt; is currently working on a utility to extend the SchemaUpdate to allow the creation of versioned database scripts like rails has (ok Adam it&amp;#39;s official, now you actually &lt;i&gt;have&lt;/i&gt; &lt;i&gt;to &lt;/i&gt;finish it!).&lt;/p&gt;
&lt;p&gt;The default AutoPersistenceModel conventions are kept quite simple, so often you will need to do a bit of customization.&amp;nbsp; One way to do this is through overrides which I showed how to use in &lt;a href="http://www.lucisferre.net/post.aspx?id=1734653d-6df8-4aa8-8aef-c264406ced37"&gt;this post&lt;/a&gt;, were I implemented an override for a self-referencing tree relationship.&amp;nbsp; However, whenever possible, it is preferable to use fluentNH&amp;#39;s conventions to do this.&amp;nbsp; Conventions can be used define custom behavior in very flexible ways.&amp;nbsp; Below I am going to show how this can be done to customize database constraints like &lt;i&gt;unique &lt;/i&gt;and &lt;i&gt;index&lt;/i&gt;. [more]&lt;/p&gt;
&lt;p&gt;S#arp Architecture provides a &lt;a href="http://wiki.sharparchitecture.net/Tutorial2DevDomainModel.ashx"&gt;[DomainSignature] attribute&lt;/a&gt; which you can apply to your entity&amp;#39;s properties.&amp;nbsp;&amp;nbsp; The attribute is used to denote the set of properties that uniquely define the entity and is similar to the concept of a &lt;i&gt;business key&lt;/i&gt; often used in SQL database design.&amp;nbsp; It is important to point out that the &lt;i&gt;DomainSignature should&lt;/i&gt;&amp;nbsp;&lt;i&gt;not be considered a primary key &lt;/i&gt;and that you should &lt;i&gt;always use a surrogate primary key&lt;/i&gt; generated either by the database or nHibernate (hilo and guid.comb are the two I prefer).&lt;/p&gt;
&lt;p&gt;The domain signature can ensures that entities can be compared using the properties decorated with [DomainSignature].&amp;nbsp; This is useful if say one object was loaded from the repository using nHibernate but another was constructed and I want to determine if I should treat them as the same entity.&amp;nbsp; It is also useful to determine if a new entity will violate a uniqueness constraint you want to enforce.&lt;/p&gt;
&lt;p&gt;A good example of a useful DomainSignature would be the slug of a blog post.&amp;nbsp; A post also has an &lt;i&gt;id &lt;/i&gt;for it&amp;#39;s primary key&lt;i&gt;,&lt;/i&gt; in most cases a guid, but the slug also uniquely identifies a post as well and no two posts can have the same slug.&amp;nbsp; The only problem now is that when I generate my DDL I can see that nHibernate has no notion that it should enforce my uniqueness constraint.&lt;/p&gt;
&lt;p&gt;What I want is for nHibernate and hence the database schema should be aware that DomainSignature implies a uniqueness constraint.&amp;nbsp; Fortunately, fluent nHibernate conventions make this is quite easy.&amp;nbsp; Fluent nHibernate defines an &lt;i&gt;AttributePropertyConvention&amp;lt;T&amp;gt;&lt;/i&gt; base class for exactly this purpose and we can extend it like this:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:5cfc2d16-0a65-4872-b026-c82df251e9a3" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;DomainSignatureConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;AttributePropertyConvention&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt;&amp;gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt; attribute, &lt;span style="color:#2b91af;"&gt;IPropertyInstance&lt;/span&gt; instance) { &lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.UniqueKey(instance.EntityType.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;DomainSignature&amp;quot;&lt;/span&gt;);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The DomainSignatureConvention tells fluent that all properties that are decorated with [DomainSignature] should form a unique key.&amp;nbsp; Now if I then define my entity like this:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:d54e305c-c2cc-4f98-a45c-8a3cb5f7b64a" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Price&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;Entity&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;span style="color:#2b91af;"&gt;DomainSignature&lt;/span&gt;]&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Security&lt;/span&gt; Security { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;span style="color:#2b91af;"&gt;DomainSignature&lt;/span&gt;]&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt; PriceDate { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;span style="color:#2b91af;"&gt;DomainSignature&lt;/span&gt;]&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; CanadianPrice { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt; Bid { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt; Ask { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt; Close { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;then SchemaExport will generate DDL like this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div id="codeSnippet" style="border-style:none;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;&lt;span style="color:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;table&lt;/span&gt; Prices (&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;    Id &lt;span style="color:#0000ff;"&gt;INTEGER&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;,&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   PriceDate DATETIME,&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   CanadianPrice &lt;span style="color:#0000ff;"&gt;INTEGER&lt;/span&gt;,&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   Bid &lt;span style="color:#0000ff;"&gt;NUMERIC&lt;/span&gt;,&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   Ask &lt;span style="color:#0000ff;"&gt;NUMERIC&lt;/span&gt;,&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   &lt;span style="color:#0000ff;"&gt;Close&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;NUMERIC&lt;/span&gt;,&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   SecurityFk &lt;span style="color:#0000ff;"&gt;INTEGER&lt;/span&gt;,&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   &lt;span style="color:#0000ff;"&gt;primary&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;key&lt;/span&gt; (Id),&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;  &lt;span style="color:#0000ff;"&gt;unique&lt;/span&gt; (PriceDate, CanadianPrice)&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;)&lt;/pre&gt;
&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;lt;!--CRLF--&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Except we have a small problem here.&amp;nbsp; The foreign key for the many-to-one relationship on &lt;i&gt;Security&lt;/i&gt; was not included in the &lt;i&gt;unique&lt;/i&gt; constraint.&amp;nbsp; To be quite honest I am not exactly sure why but I am guessing that the &lt;i&gt;AttributePropertyConvention &lt;/i&gt;does not work with a reference.&amp;nbsp; Instead I will need to add something to my &lt;i&gt;ReferenceConvention&lt;/i&gt; which is provided by default with s#arp architecture.&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:2787227c-6879-4cc5-8c9a-f06d171b4095" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ReferenceConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;IReferenceConvention&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(FluentNHibernate.Conventions.Instances.&lt;span style="color:#2b91af;"&gt;IManyToOneInstance&lt;/span&gt; instance) {&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Column(instance.Property.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;Fk&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Attribute&lt;/span&gt;.IsDefined(instance.Property, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt;)))&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.UniqueKey(&lt;span style="color:#a31515;"&gt;&amp;quot;DomainSignature&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I don&amp;#39;t really like this as I don&amp;#39;t think the attribute should be ignored, but it does at least change the above to &lt;i&gt;unique(PriceDate, CanadianPrice, SecurityFk).&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;There are obviously many other types of constraints we could use, you could create an attribute for defining indexing on certain properties like [Indexable(&amp;quot;IndexName&amp;quot;)] and create a convention like this:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:dc415913-baed-4310-ae51-951f5c4fcec1" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IndexableAttribute&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;Attribute&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; _name;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; IndexableAttribute(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; name) { _name = name; }&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; GetName() { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _name; }&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IndexableConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;AttributePropertyConvention&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IndexableAttribute&lt;/span&gt;&amp;gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(&lt;span style="color:#2b91af;"&gt;IndexableAttribute&lt;/span&gt; attribute, &lt;span style="color:#2b91af;"&gt;IPropertyInstance&lt;/span&gt; instance) {&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Index(attribute.GetName());&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now I can create indicies by using the [Indexable(&amp;quot;Name&amp;quot;)] attribute.&amp;nbsp; Properties with the same &amp;quot;Name&amp;quot; will be part of the same index constraint and indexed together.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I found it is actually a good idea to always index many-to-one relationships, something I briefly mentioned in a &lt;a href="http://www.lucisferre.net/post.aspx?id=ef779300-206b-4582-a9d0-4275b328c8c9"&gt;previous post&lt;/a&gt;.&amp;nbsp; Now that I am using fluent nhibernate however I can&amp;#39;t set the index property in the HBM files so I will need a convention for that.&amp;nbsp; It also makes sense to set this indexing on all many-to-one relationships so there is a better way to do this that does not involve the use of an attribute, instead we implement IRefrenceConvention.&amp;nbsp; S#arp architecture already includes this convention by default so we can just edit it:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:0bc6d7e9-4abf-4c45-b26d-85fa8e16fca0" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ReferenceConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;IReferenceConvention&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(FluentNHibernate.Conventions.Instances.&lt;span style="color:#2b91af;"&gt;IManyToOneInstance&lt;/span&gt; instance) {&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Column(instance.Property.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;Fk&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Attribute&lt;/span&gt;.IsDefined(instance.Property, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt;)))&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.UniqueKey(&lt;span style="color:#a31515;"&gt;&amp;quot;DomainSignature&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;else&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Index(instance.Property.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;Index&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Notice the if.else, if we have already defined &lt;i&gt;UniqueKey&lt;/i&gt; defining Index would be redundant as unique key&amp;#39;s are already indexed.&amp;nbsp; When defining indexes you will typically see something like like the following DDL output from SchemaExport:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;pre id="codeSnippet" style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;&lt;span style="color:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;index&lt;/span&gt; SecurityIndex &lt;span style="color:#0000ff;"&gt;on&lt;/span&gt; Prices (SecurityFk)&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;It is pretty easy to customize the behavior of the fluent nhibernate AutoPersistenceModel using conventions and I find it can be very useful to have this type of fine grained control over your database schema generation.&lt;/p&gt;</description></item><item><title>Customizing Fluent Nhibernate's AutoPersistenceModel Conventions</title><link>http://nhforge.org/wikis/howtonh/customizing-fluent-nhibernate-s-autopersistencemodel-conventions/revision/2.aspx</link><pubDate>Fri, 25 Dec 2009 00:38:05 GMT</pubDate><guid isPermaLink="false">45f813f2-f1c4-4eda-a619-288e3cadc793:306</guid><dc:creator>Chris Nicola</dc:creator><comments>http://nhforge.org/wikis/howtonh/customizing-fluent-nhibernate-s-autopersistencemodel-conventions/comments.aspx</comments><description>Revision 2 posted to How to by Chris Nicola on 24/12/2009 09:38:05 p.m.&lt;br /&gt;
&lt;h2&gt;Customizing Fluent Nhibernate&amp;#39;s AutoPersistenceModel Conventions&lt;/h2&gt;
&lt;div style="font-size: 90%;"&gt;Filed under: &lt;span style="background: SpringGreen;"&gt;Mapping&lt;/span&gt;&lt;span style="background: SpringGreen;"&gt;,&lt;/span&gt; FluentNH, AutoPersistenceModel, convention over configuration&lt;/div&gt;

&lt;p&gt;&lt;a href="http://www.lucisferre.net/image.axd?picture=xmlschool_1.jpg"&gt;&lt;img style="border-bottom:0px;border-left:0px;margin:0px 6px 0px 0px;display:inline;border-top:0px;border-right:0px;" title="xmlschool" src="http://www.lucisferre.net/image.axd?picture=xmlschool_thumb.jpg" alt="xmlschool" align="left" border="0" width="184" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(this was originally blogged about &lt;a href="http://www.lucisferre.net/post.aspx?id=0c0eb379-f939-406b-bfb9-a1130a5be664"&gt;here&lt;/a&gt;) &lt;/p&gt;
&lt;p&gt;One of the things I get a fair bit of use out of is the fluent nHibernate project and the AutoPersistenceModel.&amp;nbsp; If you are not very familiar with fluentNH or AutoPersistenceModel then I would suggest checking out their &lt;a href="http://wiki.fluentnhibernate.org/Main_Page"&gt;wiki&lt;/a&gt;, as what I am about to discuss, while not difficult, is some relatively advanced usage.&lt;/p&gt;
&lt;p&gt;The purpose of AutoPersistenceModel is to automatically generate the nHibernate configuration (the HBM files if you are currently used to XML configuration) directly from your model based on Convention over Configuration, &lt;a href="http://www.jameskovacs.com/blog/NETRocks475JamesKovacsOnConventionoverConfiguration.aspx"&gt;you can hear James Kovacs discuss this concept on .NET Rocks&lt;/a&gt;.&amp;nbsp; With tools like SchemaExport and SchemaUpdate it is even possible to automatically generate and execute DDL scripts against your database to keep the schema in sync with your model.&amp;nbsp; This can be a bit rails like in it&amp;#39;s use, in fact &lt;a href="http://adventuresinagile.blogspot.com/"&gt;Adam Dymitruk&lt;/a&gt; is currently working on a utility to extend the SchemaUpdate to allow the creation of versioned database scripts like rails has (ok Adam it&amp;#39;s official, now you actually &lt;i&gt;have&lt;/i&gt; &lt;i&gt;to &lt;/i&gt;finish it!).&lt;/p&gt;
&lt;p&gt;The default AutoPersistenceModel conventions are kept quite simple, so often you will need to do a bit of customization.&amp;nbsp; One way to do this is through overrides which I showed how to use in &lt;a href="http://www.lucisferre.net/post.aspx?id=1734653d-6df8-4aa8-8aef-c264406ced37"&gt;this post&lt;/a&gt;, were I implemented an override for a self-referencing tree relationship.&amp;nbsp; However, whenever possible, it is preferable to use fluentNH&amp;#39;s conventions to do this.&amp;nbsp; Conventions can be used define custom behavior in very flexible ways.&amp;nbsp; Below I am going to show how this can be done to customize database constraints like &lt;i&gt;unique &lt;/i&gt;and &lt;i&gt;index&lt;/i&gt;. [more]&lt;/p&gt;
&lt;p&gt;S#arp Architecture provides a &lt;a href="http://wiki.sharparchitecture.net/Tutorial2DevDomainModel.ashx"&gt;[DomainSignature] attribute&lt;/a&gt; which you can apply to your entity&amp;#39;s properties.&amp;nbsp;&amp;nbsp; The attribute is used to denote the set of properties that uniquely define the entity and is similar to the concept of a &lt;i&gt;business key&lt;/i&gt; often used in SQL database design.&amp;nbsp; It is important to point out that the &lt;i&gt;DomainSignature should&lt;/i&gt;&amp;nbsp;&lt;i&gt;not be considered a primary key &lt;/i&gt;and that you should &lt;i&gt;always use a surrogate primary key&lt;/i&gt; generated either by the database or nHibernate (hilo and guid.comb are the two I prefer).&lt;/p&gt;
&lt;p&gt;The domain signature can ensures that entities can be compared using the properties decorated with [DomainSignature].&amp;nbsp; This is useful if say one object was loaded from the repository using nHibernate but another was constructed and I want to determine if I should treat them as the same entity.&amp;nbsp; It is also useful to determine if a new entity will violate a uniqueness constraint you want to enforce.&lt;/p&gt;
&lt;p&gt;A good example of a useful DomainSignature would be the slug of a blog post.&amp;nbsp; A post also has an &lt;i&gt;id &lt;/i&gt;for it&amp;#39;s primary key&lt;i&gt;,&lt;/i&gt; in most cases a guid, but the slug also uniquely identifies a post as well and no two posts can have the same slug.&amp;nbsp; The only problem now is that when I generate my DDL I can see that nHibernate has no notion that it should enforce my uniqueness constraint.&lt;/p&gt;
&lt;p&gt;What I want is for nHibernate and hence the database schema should be aware that DomainSignature implies a uniqueness constraint.&amp;nbsp; Fortunately, fluent nHibernate conventions make this is quite easy.&amp;nbsp; Fluent nHibernate defines an &lt;i&gt;AttributePropertyConvention&amp;lt;T&amp;gt;&lt;/i&gt; base class for exactly this purpose and we can extend it like this:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:5cfc2d16-0a65-4872-b026-c82df251e9a3" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;DomainSignatureConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;AttributePropertyConvention&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt;&amp;gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt; attribute, &lt;span style="color:#2b91af;"&gt;IPropertyInstance&lt;/span&gt; instance) { &lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.UniqueKey(instance.EntityType.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;DomainSignature&amp;quot;&lt;/span&gt;);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The DomainSignatureConvention tells fluent that all properties that are decorated with [DomainSignature] should form a unique key.&amp;nbsp; Now if I then define my entity like this:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:d54e305c-c2cc-4f98-a45c-8a3cb5f7b64a" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Price&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;Entity&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;span style="color:#2b91af;"&gt;DomainSignature&lt;/span&gt;]&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Security&lt;/span&gt; Security { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;span style="color:#2b91af;"&gt;DomainSignature&lt;/span&gt;]&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt; PriceDate { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;span style="color:#2b91af;"&gt;DomainSignature&lt;/span&gt;]&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; CanadianPrice { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt; Bid { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt; Ask { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt; Close { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;then SchemaExport will generate DDL like this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div id="codeSnippet" style="border-style:none;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;&lt;span style="color:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;table&lt;/span&gt; Prices (&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;    Id &lt;span style="color:#0000ff;"&gt;INTEGER&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   PriceDate DATETIME,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   CanadianPrice &lt;span style="color:#0000ff;"&gt;INTEGER&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   Bid &lt;span style="color:#0000ff;"&gt;NUMERIC&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   Ask &lt;span style="color:#0000ff;"&gt;NUMERIC&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   &lt;span style="color:#0000ff;"&gt;Close&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;NUMERIC&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   SecurityFk &lt;span style="color:#0000ff;"&gt;INTEGER&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   &lt;span style="color:#0000ff;"&gt;primary&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;key&lt;/span&gt; (Id),&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;  &lt;span style="color:#0000ff;"&gt;unique&lt;/span&gt; (PriceDate, CanadianPrice)&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;)&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Except we have a small problem here.&amp;nbsp; The foreign key for the many-to-one relationship on &lt;i&gt;Security&lt;/i&gt; was not included in the &lt;i&gt;unique&lt;/i&gt; constraint.&amp;nbsp; To be quite honest I am not exactly sure why but I am guessing that the &lt;i&gt;AttributePropertyConvention &lt;/i&gt;does not work with a reference.&amp;nbsp; Instead I will need to add something to my &lt;i&gt;ReferenceConvention&lt;/i&gt; which is provided by default with s#arp architecture.&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:2787227c-6879-4cc5-8c9a-f06d171b4095" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ReferenceConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;IReferenceConvention&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(FluentNHibernate.Conventions.Instances.&lt;span style="color:#2b91af;"&gt;IManyToOneInstance&lt;/span&gt; instance) {&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Column(instance.Property.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;Fk&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Attribute&lt;/span&gt;.IsDefined(instance.Property, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt;)))&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.UniqueKey(&lt;span style="color:#a31515;"&gt;&amp;quot;DomainSignature&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I don&amp;#39;t really like this as I don&amp;#39;t think the attribute should be ignored, but it does at least change the above to &lt;i&gt;unique(PriceDate, CanadianPrice, SecurityFk).&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;There are obviously many other types of constraints we could use, you could create an attribute for defining indexing on certain properties like [Indexable(&amp;quot;IndexName&amp;quot;)] and create a convention like this:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:dc415913-baed-4310-ae51-951f5c4fcec1" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IndexableAttribute&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;Attribute&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; _name;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; IndexableAttribute(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; name) { _name = name; }&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; GetName() { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _name; }&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IndexableConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;AttributePropertyConvention&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IndexableAttribute&lt;/span&gt;&amp;gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(&lt;span style="color:#2b91af;"&gt;IndexableAttribute&lt;/span&gt; attribute, &lt;span style="color:#2b91af;"&gt;IPropertyInstance&lt;/span&gt; instance) {&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Index(attribute.GetName());&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now I can create indicies by using the [Indexable(&amp;quot;Name&amp;quot;)] attribute.&amp;nbsp; Properties with the same &amp;quot;Name&amp;quot; will be part of the same index constraint and indexed together.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I found it is actually a good idea to always index many-to-one relationships, something I briefly mentioned in a &lt;a href="http://www.lucisferre.net/post.aspx?id=ef779300-206b-4582-a9d0-4275b328c8c9"&gt;previous post&lt;/a&gt;.&amp;nbsp; Now that I am using fluent nhibernate however I can&amp;#39;t set the index property in the HBM files so I will need a convention for that.&amp;nbsp; It also makes sense to set this indexing on all many-to-one relationships so there is a better way to do this that does not involve the use of an attribute, instead we implement IRefrenceConvention.&amp;nbsp; S#arp architecture already includes this convention by default so we can just edit it:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:0bc6d7e9-4abf-4c45-b26d-85fa8e16fca0" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ReferenceConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;IReferenceConvention&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(FluentNHibernate.Conventions.Instances.&lt;span style="color:#2b91af;"&gt;IManyToOneInstance&lt;/span&gt; instance) {&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Column(instance.Property.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;Fk&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Attribute&lt;/span&gt;.IsDefined(instance.Property, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt;)))&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.UniqueKey(&lt;span style="color:#a31515;"&gt;&amp;quot;DomainSignature&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;else&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Index(instance.Property.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;Index&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Notice the if.else, if we have already defined &lt;i&gt;UniqueKey&lt;/i&gt; defining Index would be redundant as unique key&amp;#39;s are already indexed.&amp;nbsp; When defining indexes you will typically see something like like the following DDL output from SchemaExport:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;pre id="codeSnippet" style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;&lt;span style="color:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;index&lt;/span&gt; SecurityIndex &lt;span style="color:#0000ff;"&gt;on&lt;/span&gt; Prices (SecurityFk)&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;It is pretty easy to customize the behavior of the fluent nhibernate AutoPersistenceModel using conventions and I find it can be very useful to have this type of fine grained control over your database schema generation.&lt;/p&gt;</description></item><item><title>Customizing Fluent Nhibernate's AutoPersistenceModel Conventions</title><link>http://nhforge.org/wikis/howtonh/customizing-fluent-nhibernate-s-autopersistencemodel-conventions/revision/1.aspx</link><pubDate>Fri, 25 Dec 2009 00:35:49 GMT</pubDate><guid isPermaLink="false">45f813f2-f1c4-4eda-a619-288e3cadc793:305</guid><dc:creator>Chris Nicola</dc:creator><comments>http://nhforge.org/wikis/howtonh/customizing-fluent-nhibernate-s-autopersistencemodel-conventions/comments.aspx</comments><description>Revision 1 posted to How to by Chris Nicola on 24/12/2009 09:35:49 p.m.&lt;br /&gt;
&lt;p&gt;&lt;a href="http://www.lucisferre.net/image.axd?picture=xmlschool_1.jpg"&gt;&lt;img style="border-bottom:0px;border-left:0px;margin:0px 6px 0px 0px;display:inline;border-top:0px;border-right:0px;" title="xmlschool" src="http://www.lucisferre.net/image.axd?picture=xmlschool_thumb.jpg" alt="xmlschool" align="left" border="0" width="184" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(this was originally blogged about &lt;a href="http://www.lucisferre.net/post.aspx?id=0c0eb379-f939-406b-bfb9-a1130a5be664"&gt;here&lt;/a&gt;) &lt;/p&gt;
&lt;p&gt;One of the things I get a fair bit of use out of is the fluent nHibernate project and the AutoPersistenceModel.&amp;nbsp; If you are not very familiar with fluentNH or AutoPersistenceModel then I would suggest checking out their &lt;a href="http://wiki.fluentnhibernate.org/Main_Page"&gt;wiki&lt;/a&gt;, as what I am about to discuss, while not difficult, is some relatively advanced usage.&lt;/p&gt;
&lt;p&gt;The purpose of AutoPersistenceModel is to automatically generate the nHibernate configuration (the HBM files if you are currently used to XML configuration) directly from your model based on Convention over Configuration, &lt;a href="http://www.jameskovacs.com/blog/NETRocks475JamesKovacsOnConventionoverConfiguration.aspx"&gt;you can hear James Kovacs discuss this concept on .NET Rocks&lt;/a&gt;.&amp;nbsp; With tools like SchemaExport and SchemaUpdate it is even possible to automatically generate and execute DDL scripts against your database to keep the schema in sync with your model.&amp;nbsp; This can be a bit rails like in it&amp;#39;s use, in fact &lt;a href="http://adventuresinagile.blogspot.com/"&gt;Adam Dymitruk&lt;/a&gt; is currently working on a utility to extend the SchemaUpdate to allow the creation of versioned database scripts like rails has (ok Adam it&amp;#39;s official, now you actually &lt;i&gt;have&lt;/i&gt; &lt;i&gt;to &lt;/i&gt;finish it!).&lt;/p&gt;
&lt;p&gt;The default AutoPersistenceModel conventions are kept quite simple, so often you will need to do a bit of customization.&amp;nbsp; One way to do this is through overrides which I showed how to use in &lt;a href="http://www.lucisferre.net/post.aspx?id=1734653d-6df8-4aa8-8aef-c264406ced37"&gt;this post&lt;/a&gt;, were I implemented an override for a self-referencing tree relationship.&amp;nbsp; However, whenever possible, it is preferable to use fluentNH&amp;#39;s conventions to do this.&amp;nbsp; Conventions can be used define custom behavior in very flexible ways.&amp;nbsp; Below I am going to show how this can be done to customize database constraints like &lt;i&gt;unique &lt;/i&gt;and &lt;i&gt;index&lt;/i&gt;. [more]&lt;/p&gt;
&lt;p&gt;S#arp Architecture provides a &lt;a href="http://wiki.sharparchitecture.net/Tutorial2DevDomainModel.ashx"&gt;[DomainSignature] attribute&lt;/a&gt; which you can apply to your entity&amp;#39;s properties.&amp;nbsp;&amp;nbsp; The attribute is used to denote the set of properties that uniquely define the entity and is similar to the concept of a &lt;i&gt;business key&lt;/i&gt; often used in SQL database design.&amp;nbsp; It is important to point out that the &lt;i&gt;DomainSignature should&lt;/i&gt;&amp;nbsp;&lt;i&gt;not be considered a primary key &lt;/i&gt;and that you should &lt;i&gt;always use a surrogate primary key&lt;/i&gt; generated either by the database or nHibernate (hilo and guid.comb are the two I prefer).&lt;/p&gt;
&lt;p&gt;The domain signature can ensures that entities can be compared using the properties decorated with [DomainSignature].&amp;nbsp; This is useful if say one object was loaded from the repository using nHibernate but another was constructed and I want to determine if I should treat them as the same entity.&amp;nbsp; It is also useful to determine if a new entity will violate a uniqueness constraint you want to enforce.&lt;/p&gt;
&lt;p&gt;A good example of a useful DomainSignature would be the slug of a blog post.&amp;nbsp; A post also has an &lt;i&gt;id &lt;/i&gt;for it&amp;#39;s primary key&lt;i&gt;,&lt;/i&gt; in most cases a guid, but the slug also uniquely identifies a post as well and no two posts can have the same slug.&amp;nbsp; The only problem now is that when I generate my DDL I can see that nHibernate has no notion that it should enforce my uniqueness constraint.&lt;/p&gt;
&lt;p&gt;What I want is for nHibernate and hence the database schema should be aware that DomainSignature implies a uniqueness constraint.&amp;nbsp; Fortunately, fluent nHibernate conventions make this is quite easy.&amp;nbsp; Fluent nHibernate defines an &lt;i&gt;AttributePropertyConvention&amp;lt;T&amp;gt;&lt;/i&gt; base class for exactly this purpose and we can extend it like this:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:5cfc2d16-0a65-4872-b026-c82df251e9a3" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;DomainSignatureConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;AttributePropertyConvention&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt;&amp;gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt; attribute, &lt;span style="color:#2b91af;"&gt;IPropertyInstance&lt;/span&gt; instance) { &lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.UniqueKey(instance.EntityType.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;DomainSignature&amp;quot;&lt;/span&gt;);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The DomainSignatureConvention tells fluent that all properties that are decorated with [DomainSignature] should form a unique key.&amp;nbsp; Now if I then define my entity like this:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:d54e305c-c2cc-4f98-a45c-8a3cb5f7b64a" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Price&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;Entity&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;span style="color:#2b91af;"&gt;DomainSignature&lt;/span&gt;]&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Security&lt;/span&gt; Security { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;span style="color:#2b91af;"&gt;DomainSignature&lt;/span&gt;]&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt; PriceDate { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;span style="color:#2b91af;"&gt;DomainSignature&lt;/span&gt;]&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; CanadianPrice { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt; Bid { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt; Ask { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt; Close { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;then SchemaExport will generate DDL like this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div id="codeSnippet" style="border-style:none;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;&lt;span style="color:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;table&lt;/span&gt; Prices (&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;    Id &lt;span style="color:#0000ff;"&gt;INTEGER&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   PriceDate DATETIME,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   CanadianPrice &lt;span style="color:#0000ff;"&gt;INTEGER&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   Bid &lt;span style="color:#0000ff;"&gt;NUMERIC&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   Ask &lt;span style="color:#0000ff;"&gt;NUMERIC&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   &lt;span style="color:#0000ff;"&gt;Close&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;NUMERIC&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   SecurityFk &lt;span style="color:#0000ff;"&gt;INTEGER&lt;/span&gt;,&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;   &lt;span style="color:#0000ff;"&gt;primary&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;key&lt;/span&gt; (Id),&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;  &lt;span style="color:#0000ff;"&gt;unique&lt;/span&gt; (PriceDate, CanadianPrice)&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;
&lt;pre style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;)&lt;/pre&gt;
&amp;lt;!--CRLF--&amp;gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Except we have a small problem here.&amp;nbsp; The foreign key for the many-to-one relationship on &lt;i&gt;Security&lt;/i&gt; was not included in the &lt;i&gt;unique&lt;/i&gt; constraint.&amp;nbsp; To be quite honest I am not exactly sure why but I am guessing that the &lt;i&gt;AttributePropertyConvention &lt;/i&gt;does not work with a reference.&amp;nbsp; Instead I will need to add something to my &lt;i&gt;ReferenceConvention&lt;/i&gt; which is provided by default with s#arp architecture.&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:2787227c-6879-4cc5-8c9a-f06d171b4095" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ReferenceConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;IReferenceConvention&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(FluentNHibernate.Conventions.Instances.&lt;span style="color:#2b91af;"&gt;IManyToOneInstance&lt;/span&gt; instance) {&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Column(instance.Property.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;Fk&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Attribute&lt;/span&gt;.IsDefined(instance.Property, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt;)))&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.UniqueKey(&lt;span style="color:#a31515;"&gt;&amp;quot;DomainSignature&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I don&amp;#39;t really like this as I don&amp;#39;t think the attribute should be ignored, but it does at least change the above to &lt;i&gt;unique(PriceDate, CanadianPrice, SecurityFk).&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;There are obviously many other types of constraints we could use, you could create an attribute for defining indexing on certain properties like [Indexable(&amp;quot;IndexName&amp;quot;)] and create a convention like this:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:dc415913-baed-4310-ae51-951f5c4fcec1" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IndexableAttribute&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;Attribute&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; _name;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; IndexableAttribute(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; name) { _name = name; }&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; GetName() { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _name; }&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IndexableConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;AttributePropertyConvention&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IndexableAttribute&lt;/span&gt;&amp;gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(&lt;span style="color:#2b91af;"&gt;IndexableAttribute&lt;/span&gt; attribute, &lt;span style="color:#2b91af;"&gt;IPropertyInstance&lt;/span&gt; instance) {&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Index(attribute.GetName());&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now I can create indicies by using the [Indexable(&amp;quot;Name&amp;quot;)] attribute.&amp;nbsp; Properties with the same &amp;quot;Name&amp;quot; will be part of the same index constraint and indexed together.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I found it is actually a good idea to always index many-to-one relationships, something I briefly mentioned in a &lt;a href="http://www.lucisferre.net/post.aspx?id=ef779300-206b-4582-a9d0-4275b328c8c9"&gt;previous post&lt;/a&gt;.&amp;nbsp; Now that I am using fluent nhibernate however I can&amp;#39;t set the index property in the HBM files so I will need a convention for that.&amp;nbsp; It also makes sense to set this indexing on all many-to-one relationships so there is a better way to do this that does not involve the use of an attribute, instead we implement IRefrenceConvention.&amp;nbsp; S#arp architecture already includes this convention by default so we can just edit it:&lt;/p&gt;
&lt;div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:0bc6d7e9-4abf-4c45-b26d-85fa8e16fca0" class="wlWriterEditableSmartContent" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt;
&lt;div style="background:#fff;max-height:300px;overflow:auto;"&gt;&lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ReferenceConvention&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;IReferenceConvention&lt;/span&gt; {&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Apply(FluentNHibernate.Conventions.Instances.&lt;span style="color:#2b91af;"&gt;IManyToOneInstance&lt;/span&gt; instance) {&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Column(instance.Property.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;Fk&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Attribute&lt;/span&gt;.IsDefined(instance.Property, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;DomainSignatureAttribute&lt;/span&gt;)))&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.UniqueKey(&lt;span style="color:#a31515;"&gt;&amp;quot;DomainSignature&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;else&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;instance.Index(instance.Property.Name + &lt;span style="color:#a31515;"&gt;&amp;quot;Index&amp;quot;&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Notice the if.else, if we have already defined &lt;i&gt;UniqueKey&lt;/i&gt; defining Index would be redundant as unique key&amp;#39;s are already indexed.&amp;nbsp; When defining indexes you will typically see something like like the following DDL output from SchemaExport:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;pre id="codeSnippet" style="border-style:none;margin:0em;padding:0px;overflow:visible;text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;"&gt;&lt;span style="color:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;index&lt;/span&gt; SecurityIndex &lt;span style="color:#0000ff;"&gt;on&lt;/span&gt; Prices (SecurityFk)&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;It is pretty easy to customize the behavior of the fluent nhibernate AutoPersistenceModel using conventions and I find it can be very useful to have this type of fine grained control over your database schema generation.&lt;/p&gt;</description></item></channel></rss>
