<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://codebetter.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Ian Cooper [MVP]</title><subtitle type="html" /><id>http://codebetter.com/blogs/ian_cooper/atom.aspx</id><link rel="alternate" type="text/html" href="http://codebetter.com/blogs/ian_cooper/default.aspx" /><link rel="self" type="application/atom+xml" href="http://codebetter.com/blogs/ian_cooper/atom.aspx" /><generator uri="http://communityserver.org" version="3.0.20416.853">Community Server</generator><updated>2007-12-19T09:14:00Z</updated><entry><title>Architecting LINQ To SQL Applications, part 8 </title><link rel="alternate" type="text/html" href="http://codebetter.com/blogs/ian_cooper/archive/2008/04/06/architecting-linq-to-sql-applications-part-8.aspx" /><id>http://codebetter.com/blogs/ian_cooper/archive/2008/04/06/architecting-linq-to-sql-applications-part-8.aspx</id><published>2008-04-06T18:58:00Z</published><updated>2008-04-06T18:58:00Z</updated><content type="html">&lt;p&gt;Previously: &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2008/03/09/architecting-linq-to-sql-applications-part-7.aspx" class=""&gt;Architecting LINQ To SQL Applications, part 7&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;Tiers&lt;/b&gt;&lt;br /&gt;A layer, such as we discussed &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2007/11/30/architecting-linq-to-sql-applications-part-2.aspx" class=""&gt;Part 2&lt;/a&gt;, in is not a tier. A layer is a logical unit of division; a tier is a physical unit of division. The two need not be the same. Software may be layered within a single process running on one machine or across a number of processes running on different machines. Layering is about separation of concerns. Physical distribution is about sharing and scalability. So for example an RDBMS tends lives on a server, because we want to share data among many users in a scalable fashion. Some rules of thumb are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;Presentation Layer: This is the most obvious. For a rich client we need run our presentation layer on the client. Remember that we might consider a browser application to be a rich-client if it uses JavaScript and DHTML to provide its UI i.e. Ajax. For a thin client application the presentation runs on the server. &lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Application and Domain Layer: This may run in the same place as the presentation layer, and this is the most responsive option. An application server runs the application and domain logic on a server. It allows sharing of the functionality exposed by the domain across multiple clients or to other applications. Running an application server can also lower cost of upgrades in a rich-client environment, because you update the domain logic in a smaller number of places. &lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Infrastructure Services: Because the application and domain layer depend on the infrastructure services they tend to run with the application and domain layer or on their own server. &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;(As an aside, layers do not constrain packaging decisions either (i.e. how to divide your application into assemblies) and packaging decisions are again seperate from tiers. I do not intend to cover packaging decisions here. One of the best discussions is in Robert Martin&amp;#39;s &lt;a href="http://www.amazon.com/Principles-Patterns-Practices-Robert-Martin/dp/0131857258" class=""&gt;Agile Principles, Patterns, and Practices in C#&lt;/a&gt;. The &lt;a href="http://www.ndepend.com/Features.aspx" class=""&gt;NDepend&lt;/a&gt; tool is invaluable in helping you make sensible packaging decisions.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The Laws of Distribution&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The first law of distributing your application into tiers is &lt;b&gt;don’t&lt;/b&gt;. &lt;/p&gt;
&lt;p&gt;Distribution is a complexity multiplier. Increased complexity equals increased cost. Software is an economic proposition to the buyer: what benefit they receive offsets the cost of purchase and ownership. The benefits of distribution come from sharing, scalability, and quality of service. Always make tier decisions with those criteria in mind so those are the criteria which steer us in that path. &lt;a href="http://codebetter.com/blogs/david.hayden/archive/2005/07/23/129745.aspx" class=""&gt;David Hayden has talked about this issue on CodeBetter before&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Scalability&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Distribution will make your application more complicated and crossing process boundaries will make your application slower (calls across process or machine boundaries are orders of magnitude slower).&amp;nbsp; So why would we scale our application? Many application servers seem to do little beyond passing a requests to the Db to and from the UI, doing little or no processing in-between. What are people using a server for here? Connection Pooling is the major driver. If our data access happens from within the same process, then we can share connections from a pool reducing the cost of creating and destroying connections.&lt;br /&gt;&amp;nbsp; &lt;br /&gt;However, for ASP.NET applications there is little to be gained here. Indeed, a lot of people separate their domain layer into an application server in this context without needing to. We gain the benefits of connection pooling obtained from running in a single process, by virtue of being hosted within ASP.NET. There is no need to introduce a seperate application server for connection pooling here. For smart clients we can gain benefits from pooling by doing data access from a server tier, because otherwise every client will have its own connection to the Db. So at a certain point a Windows Forms application may gain a performance benefit from using an application server, but its worth bearing in mind the need to trade this benefit against the performance costs of distribution to begin with.&lt;/p&gt;
&lt;p&gt;The connection pooling example extends to anything where we have expensive creation. We may find it is more efficient to create once on the server and then allow mutliple clients to share that resource. Indeed if materialization of our objects from the Db were to be an issue then caching the objects so created and returning the cached copy from our server would relieve pressure on the Db, by allowing clients to retrieve the copy instead of re-issuing the request. However, we would need to make decisions about the importance of the liveness of our data and how our cache would be refreshed if it became invalid.&lt;/p&gt;
&lt;p&gt;In addition, where we are performing intensive activity on the server we may want to improve the performance of our application by splitting the work up and then scaling out or up. In this case we put the work into a server and share the work out among a pool of servers. Where the application server does a lot of work, for example complex calculations, then adding an application server allows the number of nodes where that calculation can be performed.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Shared Services&lt;/b&gt;&lt;br /&gt;Sharing creates pressure for a middle tier, especially if we want a service oriented architecture where there is one authority within our enteprise for certain operations. For example in an insurance company a number of applications might require access to our rating information. By hosting this information in a service we make it possible for any application within the enterpise to obtain that information. If it was locked into a smart client (for example an Excel spreadsheet) it would be difficult for other applications to share that information. A rich client cannot share the knowledge of the domain it captures, or the results of calculations, and in this circumstance you are always forced into moving this knowledge onto the server. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Quality of Service&lt;/b&gt;&lt;br /&gt;We may want to provide our application with multiple nodes to improve its fault tolerance; if we lose one node other nodes can continue to carry out work. We might want to run a service our application uses in a different security context to that which the application uses. We might want our application to use reliable messaging for an operation. All of these issues can be loosely grouped as quality of service concerns and we may want to distribute our application to avail ourself of these services.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The Last Responsible Moment&lt;/b&gt;&lt;br /&gt;Beware premature&amp;nbsp;decisions here. Just because you may need to expose this knowledge as some point, does not mean that you need to do so from the beginning. A well-layered application would be amenable to refactoring to a mult-tiered one, when you need it to be. I would try to defer the cost of distribution, until you know you need it. Bear in mind for example that a web application just uses the HTTP protocol to exchange HTML with a browser. To add a second ‘presentation’ layer that exposes XML over HTTP instead, to a calling application instead of a browser, should be a straightforward change to your existing architecture. Indeed, identifying the services the application provides may be easier if we look toward what ‘services’ we provide via HTML.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Why is there pain going multi-tier with LINQ To SQL?&lt;/b&gt;&lt;br /&gt;Assuming that you have worked through options and decided you need an N-Tier application, the question becomes: what issues will you hit when you try to use LINQ To SQL in this context.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Serialization&lt;/b&gt;&lt;br /&gt;It is not straightforward to serialize an entity between two tiers. &lt;/p&gt;
&lt;p&gt;The first issue is that XMlSerialization fails with circular-references so XMLSerialization will tend not to work where you are managing a parent-child relationship with an EntitySet-EntityRef pair. The designer does have a workaround for this in WCF, so that you don&amp;#39;t serialize both parts. There is a good summary of the issues&amp;nbsp;&lt;a href="http://oakleafblog.blogspot.com/2007/10/linq-to-sql-and-entity-framework-xml.html" class=""&gt;here&lt;/a&gt; and&amp;nbsp;&lt;a href="http://www.west-wind.com/weblog/posts/147218.aspx" class=""&gt;here&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Entity-lifetime management&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The second issue is DataContext. Remember how we talked about the &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2008/03/09/architecting-linq-to-sql-applications-part-7.aspx" class=""&gt;DataContext as a unit of work&lt;/a&gt; in which we should manage all of our interaction with entities. Passing an entity to another tier removes it from its extant unit of work. Assuming that you intend to work with the entity on another tier and then pass it back to update the Db with any changes, you will need to bear in mind that you are converting a peristent entity to a transient one and back again. There are two ways of dealing with this round trip. The first is to attach the entity to the DataContext when you deserialize it, to let the DataContext know that it is really a persistent object. As previously discussed, to effect this you think about how you will manage the &amp;#39;prior&amp;#39; state by, for example, tracking the old state of the entity yourself. The second is to think of your deserialized object as set of deltas to the current Db representation of the entity and load the entity from the Db within the current DataContext and change it to reflect the object you have deserialized. &lt;/p&gt;
&lt;p&gt;This suprises some people because they are used to working with DataSets, which formed a unit of work, and were serialized with both the old and current state of the rows they contained, allowing the updates to be played through a DataAdapter when they were passed back to the middle tier. LINQ To SQL does not support this model &amp;#39;out-of-the-box&amp;#39;. This tends to shock people who expect that the features of DataSets should somehow extend to LINQ To SQL.&lt;/p&gt;
&lt;p&gt;We&amp;#39;ll cover solutions to these issues next time, but as a teaser I would point out that the &amp;#39;Replay&amp;#39; model above is common in web applications. There we create a DataContext and load any entities required in response to a request for a page; compose an HTML response to that request from those entities and then dispose of out DataContext. If the user is editing they send a message from their browser in return with changes that indicate the modifications we want to apply to the entity. In response to that postback we load the entity from the Db again, using a fresh DataContext, and apply the edits that the user has made to it. &lt;/p&gt;
&lt;p&gt;Note how we are exchanging messages with the browser, in the form of HTML, instead of serializing objects. This basic pattern of message exchange forms the heart of how we should architect out n-tier applications when using LINQ To SQL.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=176389" width="1" height="1"&gt;</content><author><name>Ian Cooper</name><uri>http://codebetter.com/members/Ian-Cooper.aspx</uri></author><category term="Architecture" scheme="http://codebetter.com/blogs/ian_cooper/archive/tags/Architecture/default.aspx" /><category term="LINQ" scheme="http://codebetter.com/blogs/ian_cooper/archive/tags/LINQ/default.aspx" /><category term="Object-Orientation" scheme="http://codebetter.com/blogs/ian_cooper/archive/tags/Object-Orientation/default.aspx" /></entry><entry><title>Architecting LINQ To SQL Applications, part 7</title><link rel="alternate" type="text/html" href="http://codebetter.com/blogs/ian_cooper/archive/2008/03/09/architecting-linq-to-sql-applications-part-7.aspx" /><id>http://codebetter.com/blogs/ian_cooper/archive/2008/03/09/architecting-linq-to-sql-applications-part-7.aspx</id><published>2008-03-09T18:55:00Z</published><updated>2008-03-09T18:55:00Z</updated><content type="html">&lt;p&gt;Previously: &lt;a class="" href="http://codebetter.com/blogs/ian_cooper/archive/2008/03/09/previous-architecting-linq-to-sql-applications-part-5.aspx"&gt;Architecting LINQ To SQL Applications, part 6&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The topic of managing entity lifetimes&amp;nbsp;is an important one as many of the issues that people have when using an ORM for the first time relate to a lack of understanding of how an ORM manages objects loaded from the Db, or that&amp;nbsp;are to be inserted into the Db. In addition over the next few installments we will&amp;nbsp;begin to talk about some of the issues related to multi-tier&amp;nbsp;scenarios. It is important to understand how lifetime is managed because many of the issues people have come from working against the ORM rather than with it in these circumstances.&lt;/p&gt;
&lt;h3&gt;What are Entity and Value types&lt;/h3&gt;
&lt;p&gt;An &lt;em&gt;Entity&lt;/em&gt; is a type which has an identity that remains unique and consistent throughout its lifetime. It is a unique in the sense in that it must always be possible to distinguish one entity from another. It is consistent in that even if the attributes change, the entity will still retain its identity. Consider a Customer type. As an entity we must be able to distinguish one customer from another. We need to somehow define Customer identity through a member. We avoid using natural members like Name because they are not individually unique and may change over time.&amp;nbsp;Instead we base the identity of our entity&amp;nbsp;on a surrogate member that gives us identity instead. In this case we might define an Id member for our Customer that assigns them a unique&amp;nbsp;value within our organization.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Within the Db a primary key field distinguishes an entity, which is represented by a row on a table. LINQ To SQL piggybacks on this to provide support for an Entity, via a type mapped via a Table attribute or mapping, that corresponds to a table that has a primary key. So we map our Customer class to a Customer table and our Id member to an Id&amp;nbsp;primary key field on that table. Again&amp;nbsp;natural keys are allowed, but should be avoided in favour of surrogates to ensure&amp;nbsp;that our entity remains unique and identifiable throughout its lifetime.&lt;/p&gt;
&lt;p&gt;The counterpart to an Entity type is a &lt;em&gt;Value&lt;/em&gt; type. A Value type takes its identity from the value of its attributes. Two entities that have the same attributes, compare the same. For example two postcodes that have the value &amp;quot;ABC 123&amp;quot; compare the same so we consider them to have the same identity. A value type might have just the one attribute, as with our postcode example, but also might have multiple attributes. An example of a value type with multiple attributes&amp;nbsp;would be a&amp;nbsp;Money type that has both an Amount and a Currency. We want to compare two instances of Money for GBP 123.74 as equal.&lt;/p&gt;
&lt;p&gt;Within the DB a Value is represented as one or more columns within the row of an entity. LINQ To SQL only supports primitives as Values i.e. string, int, etc. and has no support for mapping user-defined value types. Thus there&amp;nbsp;is no direct support in LINQ To SQL&amp;nbsp;for types like Money. Hopefully this is a limitation that will be addressed in future versions.&lt;/p&gt;
&lt;h3&gt;Entity Lifetime&lt;/h3&gt;
&lt;p&gt;A data context is a unit of work. It tracks changes and submits updates to the Db when flushed. Because of this you should only keep it around long enough to do the work ...but no longer. When working with a DataContext we need to distinguish between, to borrow Hibernate terminology, &lt;em&gt;transient&lt;/em&gt; and &lt;em&gt;persistent&lt;/em&gt; entities. &lt;/p&gt;
&lt;p&gt;Persistent objects have been loaded by LINQ To SQL and we have a reference to them in the DataContext’s identity map. The DataContext tracks changes for the persistent entity against the time that they were loaded. Future requests for that object, will return the object in the cache. Changes to that entity can be submitted to the Db.&amp;nbsp; Lazy Loading of associations, uses the same DataContext we loaded the entity with originally.&lt;/p&gt;
&lt;p&gt;An entity that is not in the identity map of the DataContext is a transient entity. It has a lifetime equivalent to the running application. To ensure that the entity persists we need to add it the matching table on the DataContext using InsertOnSubmit and flush it using SubmitChanges on the DataContext, causing the entity to become persistent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MyContext context = new MyContext();&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;//persistent object&lt;br /&gt;MyObject myOldObject = context.MyObjects.Where(m =&amp;gt; m.Name == &amp;quot;Old&amp;quot;).Single();&lt;br /&gt;//changes are tracked&lt;br /&gt;myOldObject.Name = &amp;quot;Changed Name&amp;quot;;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;//new entity; transient&lt;br /&gt;MyObject myNewobject = new MyObject();&lt;br /&gt;//no need to track; no Db row to update yet&lt;br /&gt;myNew.Name = &amp;quot;New Name&amp;quot;;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;//make new object persistent and flush changes to old objects&lt;br /&gt;context.SubmitChanges(); &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is not always intuitive:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MyContext anotherContext= new MyContext();&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;//new entity; transient&lt;br /&gt;MyObject myNewobject = new MyObject();&lt;br /&gt;myNew.Name = &amp;quot;New Name&amp;quot;;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;//new entity is still transient until we actually submit&lt;br /&gt;anotherContext.MyObjects.InsertOnSubmit(myNewobject);&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;//not persistent, won&amp;#39;t be found&lt;br /&gt;var results = anotherContext.MyObjects.Where(m =&amp;gt; m.Name == &amp;quot;Old&amp;quot;);&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It is important to note that although an identity map is sometimes called a first-level cache its purpose is not to optimize retrieval of entities from the Db. Because the ORM, such as LINQ To SQL does not know the results of a query it cannot determine whether two calls to a query (even if it is the same query as other users may have updated the Db) will return the same result set. For this reason it must always bring the result set back, and then check for the existence of those entities within the identity map. If the map contains the item, we must return that instance instead because you might have made changes to the entity and we want to preserve them througout the unit of work. For this reason the cache is not about optimisation but about ensuring you do not lose changes during your unit of work. It is possible that queries that request an entity by primary key could be retrieved from the map directly, where they are already loaded, but you should not rely on this optimization.&lt;/p&gt;
&lt;p&gt;Because we hold the object within the identity map for the lifetime of the unit of work there is a danger of concurrency errors, where another user updates the Db while we have the object. For this reason the identity map stores the original version of our object as well as the current one. This allows LINQ To SQL to compare the original against the state of the Db when it issues an update or delete query and raise an optimistic concurrency violation error if it has changed. Of course if you use a timestamp and set &lt;strong&gt;Update.Never&lt;/strong&gt; on your mapping to inform LINQ To SQL that it should not check that field when looking for concurrency errors you can optimize this feature as well. However the optimal SQL issues by LINQ To SQL during an update still depends on knowing what has changed.&lt;/p&gt;
&lt;p&gt;LINQ To SQL supports a Refresh method on its DataContext to force a reload of an entity or attributes of an entity. The purpose here is to allow you to resolve optimistic concurrency errors or to reload an object during a unit of work if you are aware that the Db has been changed by a mechanism outside of the purview of LINQ To SQL. The Refresh just goes back to the Db to find the latest version of your object. Note that refresh targets specific objects in the map or a set of objects.&lt;/p&gt;
&lt;p&gt;You can disable use of the identity map by setting &lt;strong&gt;ObjectTrackingEnabled&lt;/strong&gt; to false. The purpose here is to optimize when you are loading read-only collections i.e. you never want to submit changes on these objects back to the Db. Remember though that another DataContext will consider these to be transient objects, so avoid assigning references loaded this way into entities loaded via DataContexts which&amp;nbsp;are tracking.&lt;/p&gt;
&lt;h3&gt;Attaching Entities&lt;/h3&gt;
&lt;p&gt;Sometimes we have an entity that is in the backing store but not in the identity cache of our DataContext. To make our DataContext aware that this is a persistent and not transient entity we need to Attach it to our DataContext. This puts it in our cache. However, our context&amp;nbsp;cannot know if the entity is the same as the representation on the backing store, so it must assume so and change tracking will consider your object to be in the ‘original’ state.&amp;nbsp; If your object has changed and you try to save those errors, you will get optimistic concurrency errors. This is because when we compare your ‘original’ to the Db, they do not match, which fools LINQ To SQL into thinking another user has changed it since we loaded it. &lt;/p&gt;
&lt;p&gt;One option to avoid you must tell the DataContext what the original state in the Db was or set your columns as &lt;strong&gt;UpdateCheck.Never&lt;/strong&gt;. If you have a Timestamp column, you can rely on that to do the right thing for you. Sometimes people suggest an&amp;nbsp;&lt;strong&gt;Update.Never&lt;/strong&gt; on every column strategy, where you cannot use a timestamp,&amp;nbsp;but the danger is that&amp;nbsp;we can overwrite genuine changes by another user. &lt;/p&gt;
&lt;p&gt;Otherwise we need to either provide the original, by maintaining the original state for any objects we may choose to detach, or adopt a load and replay strategy for detached objects where we load the current representation from the Db and then write our changes over it. &lt;/p&gt;
&lt;p&gt;Think carefully before heading down the detached objects route as it multiplies the complexity of what you are doing. This issue most often raises its head in multi-tier scenarios. We will talk about how to handle those in a future blog post, but for now recognize that the unit of work implies that the framework will not help you track changes outside of that context.&lt;/p&gt;
&lt;h3&gt;Managing DataContexts&lt;/h3&gt;
&lt;p&gt;Do not try to work with two different contexts at the same time. This is because what are persistent entities for one look like transient entities to the other because it does not have them in its identity map, as it did not load them.&lt;/p&gt;
&lt;p&gt;Do not try to access an object graph loaded via LINQ To SQL outside of its DataContext if it has lazy loaded properties. This is because LINQ To SQL will access the original DataContext to load the entities.&amp;nbsp; Trying to lazy load within another context falls foul of our earlier rule not to mix our contexts.&lt;/p&gt;
&lt;p&gt;Finally, assume that a DataContext is not thread safe i.e. work with a DataContext only on one thread and do not try to pass entities retrieved via a DataContext on one thread, to another thread.&lt;/p&gt;
&lt;p&gt;When working with a web application consider creating a DataContext per http request, using it to retrieve and then submit any changes required by the session. For a client-side application consider using a DataContext for each application transaction. &lt;/p&gt;
&lt;p&gt;While a DataContext is disposable, only dispose of it when you finish your request or application/transaction and are finished with the persistent entities that it loaded.&lt;/p&gt;
&lt;p&gt;Exercise caution around caching entities that were loaded via a DataContext. This is because when you access those elements they may still refer to the DataContext if they contain a lazy loaded association. If you want to use LINQ To SQL to load cached data, make sure you load objects that are not coupled to the DataContext, by not using EntitySet&amp;lt;&amp;gt; and EntityRef&amp;lt;&amp;gt; for associations, and disabling deferred loading on the context that you use to load them. This can be appropriate for reference data, in which case, you can also disable change tracking. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is LINQ To SQL deficient here?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&amp;nbsp;read&amp;nbsp; a fair number of opinions that are suprised by the behavior of LINQ To SQL. However, having used ORMs for a number of years, I find LINQ To SQL conforms to my expectations as to how an ORM should behave.&amp;nbsp;Indeed a reading of something as old now as Martin Fowler&amp;#39;s &lt;a class="" href="http://www.amazon.com/Enterprise-Application-Architecture-Addison-Wesley-Signature/dp/0321127420"&gt;Patterns of Enteprise Application Architecture&lt;/a&gt; and you will find exactly this pattern of behavior for an ORM discussed. Indeed &lt;a class="" href="http://code.google.com/p/wilsonormapper/"&gt;WORM&lt;/a&gt; (Wilson O/R Mapper now open source BTW) and &lt;a class="" href="http://www.hibernate.org/343.html"&gt;NHibernate&lt;/a&gt; both behave in a similar fashion. So some of this seems to be based on expectations that don&amp;#39;t come from experience of using ORM tools. On a recent &lt;a class="" href="http://www.dotnetrocks.com/default.aspx?showNum=90"&gt;.NET Rocks&lt;/a&gt; there was an opinion expressed that LINQ To SQL was somehow only fit to be a RAD tool because of multi-tier issues. I can&amp;#39;t agree with this opinion at all. LINQ To SQL has a similar feature set to WORM, on which I have built distributed enterprise applications. Its limitations relate to the diversity of mappings that it supports (table per concrete class in an inheritance hierachy or value types for example) and its lack of support for multiple Db vendors, not some percieved issues around the unit of work and identity map patterns which it implements. &lt;/p&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=175109" width="1" height="1"&gt;</content><author><name>Ian Cooper</name><uri>http://codebetter.com/members/Ian-Cooper.aspx</uri></author><category term="Featured" scheme="http://codebetter.com/blogs/ian_cooper/archive/tags/Featured/default.aspx" /><category term="LINQ" scheme="http://codebetter.com/blogs/ian_cooper/archive/tags/LINQ/default.aspx" /></entry><entry><title>Architecting LINQ To SQL Applications, part 6</title><link rel="alternate" type="text/html" href="http://codebetter.com/blogs/ian_cooper/archive/2008/03/09/previous-architecting-linq-to-sql-applications-part-5.aspx" /><id>http://codebetter.com/blogs/ian_cooper/archive/2008/03/09/previous-architecting-linq-to-sql-applications-part-5.aspx</id><published>2008-03-09T18:01:00Z</published><updated>2008-03-09T18:01:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;Previous&lt;/strong&gt;: &lt;a class="" href="http://codebetter.com/blogs/ian_cooper/archive/2008/02/17/architecting-linq-to-sql-applications-part-5.aspx"&gt;Architecting LINQ To SQL Applications, part 5&lt;/a&gt; &lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Mapping with XML files instead of Attributes&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a class="" href="http://codebetter.com/blogs/gregyoung/default.aspx"&gt;Greg Young&lt;/a&gt;&amp;nbsp;pointed out in the comments to the last post that using attributes can clutter your domain objects. Although it is simpler to show attributes first, so that you can relate rolling your own mappings to the designer generated code, I did not want to leave the story incomplete without showing you how to move those mappings into a file in order to keep your domain objects clean.&lt;/p&gt;
&lt;p&gt;The correspondence between the mapping file and the attributes is straightforward. Instead of attributes we just have XML elements and instead of properties on those attributes, we have attributes on our XML elements.&lt;/p&gt;
&lt;p&gt;First of all we need to create a text file to hold our mappings. We call it Keysafe.map. Next we need to indicate the xml encoding:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now we need to open up a Database element, which will form the root of our mapping.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;lt;Database Name=&amp;quot;northwind&amp;quot; xmlns=&amp;quot;&lt;/strong&gt;&lt;a href="http://schemas.microsoft.com/linqtosql/mapping/2007"&gt;&lt;strong&gt;http://schemas.microsoft.com/linqtosql/mapping/2007&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;/Database&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Within the Database element we need to add a Table element for each entity we wish to map (equivalent to our [Table] attribute).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;Database Name=&amp;quot;northwind&amp;quot; xmlns=&amp;quot;&lt;/strong&gt;&lt;a href="http://schemas.microsoft.com/linqtosql/mapping/2007"&gt;&lt;strong&gt;http://schemas.microsoft.com/linqtosql/mapping/2007&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;Table Name=&amp;quot;dbo.Category&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/Table&amp;gt;&lt;br /&gt;&amp;lt;/Database&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Because we are not using an attribute we have to tell LINQ To SQL what type our table maps to explicitly:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;Database Name=&amp;quot;northwind&amp;quot; xmlns=&amp;quot;&lt;/strong&gt;&lt;a href="http://schemas.microsoft.com/linqtosql/mapping/2007"&gt;&lt;strong&gt;http://schemas.microsoft.com/linqtosql/mapping/2007&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;Table Name=&amp;quot;dbo.Category&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;Type Name=&amp;quot;KeySafeDomain.Category&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/Type&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/Table&amp;gt;&lt;br /&gt;&amp;lt;/Database&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Then we need to map out our Columns. Again because we are not associating our attribute with a member, we have to explicitly indicate the member.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;Database Name=&amp;quot;northwind&amp;quot; xmlns=&amp;quot;&lt;/strong&gt;&lt;a href="http://schemas.microsoft.com/linqtosql/mapping/2007"&gt;&lt;strong&gt;http://schemas.microsoft.com/linqtosql/mapping/2007&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;Table Name=&amp;quot;dbo.Category&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;Type Name=&amp;quot;KeySafeDomain.Category&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Column Name=&amp;quot;Id&amp;quot; Member=&amp;quot;Id&amp;quot; DbType=&amp;quot;Int NOT NULL IDENTITY&amp;quot; IsPrimaryKey=&amp;quot;true&amp;quot; IsDbGenerated=&amp;quot;true&amp;quot; UpdateCheck=&amp;quot;Never&amp;quot; AutoSync=&amp;quot;OnInsert&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Column Name=&amp;quot;Name&amp;quot; Member=&amp;quot;Name&amp;quot; DbType=&amp;quot;NVarChar(50) NOT NULL&amp;quot; CanBeNull=&amp;quot;false&amp;quot; UpdateCheck=&amp;quot;Never&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Column Name=&amp;quot;ParentId&amp;quot; Member=&amp;quot;ParentId&amp;quot; DbType=&amp;quot;Int&amp;quot; UpdateCheck=&amp;quot;Never&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Column Name=&amp;quot;Version&amp;quot; Member=&amp;quot;Version&amp;quot; DbType=&amp;quot;rowversion NOT NULL&amp;quot; CanBeNull=&amp;quot;false&amp;quot; IsDbGenerated=&amp;quot;true&amp;quot; IsVersion=&amp;quot;true&amp;quot; AutoSync=&amp;quot;Always&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/Type&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/Table&amp;gt;&lt;br /&gt;&amp;lt;/Database&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As before the DbType information is there to help us generate the Db from our domain model.&lt;/p&gt;
&lt;p&gt;We also need to map out the associations between our classes. Again the conversion between the attribute based model and our XML model is straightforward.&lt;/p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Association&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Children&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Storage&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;children&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;ThisKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;ParentId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;OtherKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Id&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;/&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Association&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Parent&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Storage&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;parent&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;ThisKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;ParentId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;/&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Association&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Systems&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Storage&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;systems&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;OtherKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;CategoryId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;/&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&lt;/font&gt;&lt;/strong&gt;At this point it is just grunt work to translate our previous attribute based mappings into an XML mapping file. &lt;/p&gt;
&lt;p&gt;In the end our mapping looks like this:&lt;/p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2"&gt;&amp;lt;?&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;xml&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;version&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;1.0&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;encoding&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;utf-8&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;?&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Database&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;northwind&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;xmlns&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;http://schemas.microsoft.com/linqtosql/mapping/2007&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Table&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;dbo.Category&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Type&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;KeySafeDomain.Category&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Id&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Id&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Int NOT NULL IDENTITY&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsPrimaryKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsDbGenerated&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;AutoSync&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;OnInsert&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Name&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Name&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;NVarChar(50) NOT NULL&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;CanBeNull&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;false&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;ParentId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;ParentId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Int&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Version&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Version&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;rowversion NOT NULL&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;CanBeNull&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;false&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsDbGenerated&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsVersion&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;AutoSync&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Always&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Association&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Children&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Storage&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;children&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;ThisKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;ParentId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;OtherKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Id&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;/&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Association&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Parent&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Storage&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;parent&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;ThisKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;ParentId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;/&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Association&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Systems&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Storage&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;systems&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;OtherKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;CategoryId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;/&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Type&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/p&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Table&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Table&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;dbo.ITSystem&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Type&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;KeySafeDomain.ITSystem&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;CategoryId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;CategoryId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Int NOT NULL&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Comments&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Comments&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;NVarChar(4000)&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Name&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Name&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;NVarChar(50) NOT NULL&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;CanBeNull&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;false&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Id&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Id&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Int NOT NULL IDENTITY&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsPrimaryKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsDbGenerated&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;AutoSync&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;OnInsert&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Version&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Version&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;rowversion NOT NULL&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;CanBeNull&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;false&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsDbGenerated&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsVersion&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;AutoSync&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Always&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Association&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Keys&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Storage&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;keys&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;OtherKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;SystemId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;/&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Association&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Category&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Storage&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;category&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;OtherKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Id&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;ThisKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;CategoryId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;/&amp;gt;&lt;/p&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Type&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Table&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Table&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;dbo.Key&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Type&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;KeySafeDomain.Key&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Id&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Id&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Int NOT NULL IDENTITY&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsPrimaryKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsDbGenerated&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;AutoSync&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;OnInsert&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Password&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Password&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;NVarChar(50) NOT NULL&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;CanBeNull&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;false&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;SystemId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;SystemId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Int NOT NULL&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;UserName&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;UserName&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;NVarChar(50) NOT NULL&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;CanBeNull&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;false&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;UpdateCheck&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Never&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Column&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Name&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Version&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Version&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;DbType&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;rowversion NOT NULL&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;CanBeNull&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;false&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsDbGenerated&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;IsVersion&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;true&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;AutoSync&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Always&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; /&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Association&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Member&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;System&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;Storage&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;system&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;OtherKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;Id&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;font color="#ff0000" size="2"&gt;ThisKey&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;=&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;SystemId&lt;/font&gt;&lt;font size="2"&gt;&amp;quot;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;/&amp;gt;&lt;/p&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Type&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Table&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/p&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#a31515" size="2"&gt;Database&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt; 
&lt;p&gt;&lt;/font&gt;&lt;/strong&gt;We can then delete all of our mappings from our domain model so that our model is clean.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class Category&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private EntitySet&amp;lt;Category&amp;gt; children = new EntitySet&amp;lt;Category&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Id { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name {get;set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int? ParentId { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private EntityRef&amp;lt;Category&amp;gt; parent;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private EntitySet&amp;lt;ITSystem&amp;gt; systems = new EntitySet&amp;lt;ITSystem&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public byte[] Version {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class Key&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Id { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Password { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int SystemId { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private EntityRef&amp;lt;ITSystem&amp;gt; system = default(EntityRef&amp;lt;ITSystem&amp;gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string UserName { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public byte[] Version {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class ITSystem&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int CategoryId { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;private EntityRef&amp;lt;Category&amp;gt; category = default(EntityRef&amp;lt;Category&amp;gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Comments {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name {get;set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Id { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private EntitySet&amp;lt;Key&amp;gt; keys = new EntitySet&amp;lt;Key&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public byte[] Version {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Managing the Mapping File&lt;/strong&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;I often embed the file into the dll that contains the model. The upside here is that you don&amp;#39;t need to worry about deployment, but the downside is that you cannot change the mapping without re-issuing the DLL. If you embed the mapping file, you will need some code to read it, so that you can pass it into the DataContext. I use a helper class like this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static class Mapping&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static XmlMappingSource GetMapping()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XmlMappingSource mapping;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(&amp;quot;KeySafeDomain.Mappings.Keysafe.map&amp;quot;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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; mapping = XmlMappingSource.FromStream(stream);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return mapping;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Then we just grab the mapping when we construct our typesafe DataContext:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public KeySafeContext() : base(ConfigurationManager.ConnectionStrings[DbName].ConnectionString, KeySafeDomain.Mappings.Mapping.GetMapping())&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Systems = GetTable&amp;lt;ITSystem&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Keys = GetTable&amp;lt;Key&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Categories = GetTable&amp;lt;Category&amp;gt;();&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataLoadOptions dataLoadOptions = new DataLoadOptions();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dataLoadOptions.LoadWith&amp;lt;ITSystem&amp;gt;(s=&amp;gt;s.Keys);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;With that done we can re-run our tests to check that everything passes.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=175105" width="1" height="1"&gt;</content><author><name>Ian Cooper</name><uri>http://codebetter.com/members/Ian-Cooper.aspx</uri></author><category term="LINQ" scheme="http://codebetter.com/blogs/ian_cooper/archive/tags/LINQ/default.aspx" /></entry><entry><title>Developer Day Ireland</title><link rel="alternate" type="text/html" href="http://codebetter.com/blogs/ian_cooper/archive/2008/03/06/developer-day-ireland.aspx" /><id>http://codebetter.com/blogs/ian_cooper/archive/2008/03/06/developer-day-ireland.aspx</id><published>2008-03-06T08:54:00Z</published><updated>2008-03-06T08:54:00Z</updated><content type="html">&lt;p&gt;A while back I posted about the &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2007/11/28/whither-ddd.aspx"&gt;future of Developer Day&lt;/a&gt; (called &lt;a href="http://www.dddireland.com/"&gt;DDD &lt;/a&gt;here, but not to be confused with &lt;a href="http://www.domaindrivendesign.org/"&gt;Domain Driven Design&lt;/a&gt;). For the international audience DDD is was inspired by US &lt;a href="http://blogs.msdn.com/trobbins/archive/2004/12/12/280181.aspx"&gt;Code&amp;nbsp; Camps&lt;/a&gt;,  and has a similar by and for the community agenda.&lt;/p&gt;&lt;p&gt;One of the issues I raised was that the UK &amp;amp; IE only had one Code Camp event. Although we ran it twice a year, it was always over-subscribed, suggesting that there was a huge demand for on-the-weekend community events. We have always seemed a big enough place to hold a lot more regional events. Back when I last blogged I mentioned &lt;a href="http://www.developerdayscotland.com/"&gt;DDD Scotland&lt;/a&gt; and now I am pleased to note that there will be a &lt;a href="http://www.dddireland.com/"&gt;DDD Ireland on Saturday May 3rd&lt;/a&gt;. It&amp;#39;s great to see the community events spreading. It is good to see some ALT.NET topics in the agenda too, &lt;a href="http://blog.benhall.me.uk/"&gt;Ben&lt;/a&gt; is going to be be talking about TDD, &lt;a href="http://www.daveandal.net/alshed/sellingmysoul/default.asp"&gt;Alex Homer&lt;/a&gt; (who I guess breaks the rules once he goes to work at the P&amp;amp;P team, but I guess he gets away with it this time around) on Dependency Injection, and Mike Azocar talking about Scrum. &lt;/p&gt;&lt;p&gt;I would still like to see more people across the UK + IE &lt;a href="http://weblogs.asp.net/bsimser/archive/2007/10/11/ryo-altnetconf.aspx"&gt;holding local altnet conferences&lt;/a&gt;. Come on us Londoners can&amp;#39;t have all the fun. They are a lot easier to organize than a DDD style event, as they are mostly self-organizing.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=174984" width="1" height="1"&gt;</content><author><name>Ian Cooper</name><uri>http://codebetter.com/members/Ian-Cooper.aspx</uri></author></entry><entry><title>Some recommended books</title><link rel="alternate" type="text/html" href="http://codebetter.com/blogs/ian_cooper/archive/2008/03/04/some-recommended-books.aspx" /><id>http://codebetter.com/blogs/ian_cooper/archive/2008/03/04/some-recommended-books.aspx</id><published>2008-03-04T12:39:00Z</published><updated>2008-03-04T12:39:00Z</updated><content type="html">&lt;p&gt;A couple of people at the &lt;a href="http://www.basta.net/"&gt;BASTA &lt;/a&gt;conference asked me for book recommendations for people who were trying to get a better idea of how to do solution design. At the same time, a couple of people at my TDD Best Practices talk at the &lt;a href="http://www.dnug.org.uk"&gt;London .NET user group&lt;/a&gt; asked me to remind them about book recommendations. I promised to put the titles we discussed on my blog, so here we go.&lt;/p&gt;&lt;p&gt;This is list is not meant to be exhaustive, but I think it represents a good starting point. I am sure there are many books I have left out that people like, but I wanted to keep the list to a manageable number for people to think about tackling. They are all ones I have found real value in and keep referring to (usually via &lt;a href="http://safari.oreilly.com/"&gt;Safari &lt;/a&gt;nowadays).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Design&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Head-First-Design-Patterns/dp/0596007124/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1204621118&amp;amp;sr=8-1"&gt;Head First Design Patterns&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.amazon.com/Principles-Patterns-Practices-Robert-Martin/dp/0131857258/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1204621149&amp;amp;sr=8-1"&gt;Agile Principles, Patterns, and Practices in C#&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Enterprise-Application-Architecture-Addison-Wesley-Signature/dp/0321127420/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1204621220&amp;amp;sr=1-1"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Enterprise-Integration-Patterns-Designing-Addison-Wesley/dp/0321200683/ref=pd_bxgy_b_text_b"&gt;Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=pd_sim_b_img_1"&gt;Domain-Driven Design: Tackling Complexity in the Heart of Software&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Applying-Domain-Driven-Design-Patterns-Examples/dp/0321268202/ref=pd_sim_b_img_3"&gt;Applying Domain-Driven Design and Patterns: With Examples in C# and .NET&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Object-Design-Responsibilities-Collaborations-Addison-Wesley/dp/0201379430/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1204621434&amp;amp;sr=1-1"&gt;Object Design: Roles, Responsibilities, and Collaborations&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Test-Driven Development&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530/ref=pd_bbs_sr_3?ie=UTF8&amp;amp;s=books&amp;amp;qid=1204621467&amp;amp;sr=1-3"&gt;Test Driven Development: By Example&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Working-Effectively-Legacy-Robert-Martin/dp/0131177052/ref=pd_sim_b_img_4"&gt;Working Effectively with Legacy Code&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Refactoring-Improving-Existing-Addison-Wesley-Technology/dp/0201485672/ref=pd_sim_b_img_2"&gt;Refactoring: Improving the Design of Existing Code&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/xUnit-Test-Patterns-Refactoring-Addison-Wesley/dp/0131495054/ref=pd_sim_b_img_5"&gt;xUnit Test Patterns: Refactoring Test Code&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=174897" width="1" height="1"&gt;</content><author><name>Ian Cooper</name><uri>http://codebetter.com/members/Ian-Cooper.aspx</uri></author></entry><entry><title>Architecting LINQ To SQL Applications, part 5</title><link rel="alternate" type="text/html" href="http://codebetter.com/blogs/ian_cooper/archive/2008/02/17/architecting-linq-to-sql-applications-part-5.aspx" /><id>http://codebetter.com/blogs/ian_cooper/archive/2008/02/17/architecting-linq-to-sql-applications-part-5.aspx</id><published>2008-02-17T17:35:00Z</published><updated>2008-02-17T17:35:00Z</updated><content type="html">&lt;p&gt;Let&amp;#39;s return to the series on how to architect applications that use LINQ To SQL. First of all, for those you who missed it, a summary of where we have been:&lt;/p&gt;
&lt;p&gt;&lt;a class="" href="http://codebetter.com/blogs/ian_cooper/archive/2007/11/29/architecting-linq-to-sql-applications-part-1.aspx"&gt;Part 1, Introduction&lt;/a&gt;&lt;br /&gt;&lt;a class="" href="http://codebetter.com/blogs/ian_cooper/archive/2007/11/30/architecting-linq-to-sql-applications-part-2.aspx"&gt;Part 2, Layered Architectures&lt;/a&gt;&lt;br /&gt;&lt;a class="" href="http://codebetter.com/blogs/ian_cooper/archive/2007/12/02/architecting-linq-to-sql-applications-part-3.aspx"&gt;Part 3, DAOs and Repositories&lt;/a&gt;&lt;br /&gt;&lt;a class="" href="http://codebetter.com/blogs/ian_cooper/archive/2007/12/04/architecting-linq-to-sql-applications-part-4.aspx"&gt;Part 4, Dynamic Queries&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I had a couple of requests to provide some sample code. So I delayed this installment to start building something that will work to that purpose as the backbone for these articles. In the example we are modelling a system that allows us to store usernames and passwords for systems we own, just because that is a side project I am working on. It will go up on Google code toward the end of the series. I also had a number of requests to talk more about mapping and TDD, so this installment returns to that territory in more detail.&lt;/p&gt;
&lt;p&gt;First, imagine that we have built some domain objects through Test-Driven Development. In our model an ITSystem has a collection of Keys (username and password) to systems and belongs to a Category.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp; public class ITSystem&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Category Category {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Comments {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name {get;set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public List&amp;lt;Key&amp;gt; Keys {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;We&amp;#39;ve built our domain model before we create a database schema to store it against. We know we do need to store it, but we want to be malleable until we do. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Aggregates and Repositories&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Within our domain we have repositories, which represent a collection of our objects and negotiates with infrastrtucture services to get that list of objects. We don&amp;#39;t define a repository&amp;nbsp; for all of our entities, but for the root entities within an aggregate:&lt;/p&gt;
&lt;p&gt;&amp;quot;An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each AGGREGATE has a root and a boundary. The boundary defines what is inside the AGGREGATE. The root is a single, specific ENTITY contained in the AGGREGATE. The root is the only member of the AGGREGATE that outside objects are allowed to hold references to, although objects within the boundary may hold references to each other. ENTITIES other than the root have local identity, but that identity needs to be distinguishable only within the AGGREGATE, because no outside object can ever see it out of the context of the root ENTITY&amp;quot; [Evans]&lt;/p&gt;
&lt;p&gt;In our example the root is ITSystem and the boundary includes the Keys for that system. We don&amp;#39;t include Category within the boundary. Although an ITSystem has a category it does not manage the lifecycle of a Category. Deleting an ITSystem does not delete the Category it belongs to.&amp;nbsp; As a corollary we might delete a Category, without deleting the IT System, if, for example, we were re-categorizing our systems.&lt;/p&gt;
&lt;p&gt;Within our Category and ITSystem aggregates we can hold references to each other&amp;#39;s root objects, but nothing below them. This does not make a huge difference here, because there are only two aggregates we care about: ITSystem and Category, but the point remains.&lt;/p&gt;
&lt;p&gt;When working with an ORM I tend to view the point of crossing an aggregate boundaries as a good candidate for lazy loading. As well as using the collection based lazy loading common in ORMs you might also want to think about using a ghost [Fowler]. Of course beware the select N+1 problem if you know that you are likely to load a collection.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Working in memory&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So we need a repository that allows us to retrieve/persist the ITSystem root and its child Keys. We can write a unit test for that:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [TestClass]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class ITSytemRepositoryFixture&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [TestMethod]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Should_Be_Able_To_Find_All_Systems()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //setup&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MockRepository mocks = new MockRepository();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ISession session = mocks.Stub&amp;lt;ISession&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session.Systems = CreateSystemList();&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SystemRepository systemRepository = new SystemRepository(session);&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //exercise&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;ITSystem&amp;gt; systems = systemRepository.FindAll();&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //verify&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AssertSystemListMatches(session, systems);&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We are not showing the creation method CreateSystemList or the verification method: AssertSystemListMatches here, for simplicity. &lt;/p&gt;
&lt;p&gt;The session will end up abstracting DataContext. It is our unit of work and has both the methods we need to submit changes, and contains the collections that we are accessing. &lt;/p&gt;
&lt;p&gt;Remember how in part 3 we stated that when we crossed a layer boundary we wanted to depend upon an abstraction and not a concrete type. A proof here is that depending on an abstract type allows us to replace the real data context for unit tests. In the unit test we replace the dependency from the DataContext based repository with a in-memory stub implementation which acts as a Test Double for Db operations.&lt;/p&gt;
&lt;p&gt;Note that I am not accessing the Db here, I am just building up the functionality of the repository. Within the implementation we use LINQ to return the result set. Note that this is so simple a case, as an example, that the use of LINQ may seem overcomplex, but we don&amp;#39;t want to distract with complexity here. &lt;/p&gt;
&lt;p&gt;My implementation looks like this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class SystemRepository&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private ISession session;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Initializes a new instance of the SystemRepository class.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;param name=&amp;quot;session&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public SystemRepository(ISession session)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.session = session;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Find all the systems&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public List&amp;lt;ITSystem&amp;gt; FindAll()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&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; (from s in session.Systems&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; select s)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ToList&amp;lt;ITSystem&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mapping&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;We can go a long way working with this in-memory representation, building up the queries our repository manages for us against the&amp;nbsp; domain layer without ever touching peristence to a Db. Because we are not touching the Db as yet we are very malleable. We don&amp;#39;t have to worry about versioning Db schemas. Where there is a lack of resistance to change, we tend to make more effort to keep our code clean.&lt;/p&gt;
&lt;p&gt;Of course at some point we want to write the code that will persist our domain model. Again we can drive with tests. &lt;/p&gt;
&lt;p&gt;Because these tests will be slow, we are touching the Db, we put them in a seperate assembly and tag them as Slow or Acceptance tests. Developers may want to skip running these tests when confirming their refactoring up until they check-in, so they don&amp;#39;t break the rhythm.&lt;/p&gt;
&lt;p&gt;We could have an equivalent test to that above:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [TestClass]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class ITSytemRepositoryFixture: ITSystemTests&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [TestMethod]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Should_Be_Able_To_Find_All_Systems()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //setup&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ISession session = new KeySafeSession(new DataContext(ConfigurationManager.ConnectionStrings[&amp;quot;KeySafe&amp;quot;].ConnectionString));&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SystemRepository systemRepository = new SystemRepository(session);&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //exercise&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;ITSystem&amp;gt; systems = systemRepository.FindAll();&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //verify&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AssertSystemListMatches(session, systems);&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;But note how this time we are using a concrete session implementation initialized from our DataContext.&lt;/p&gt;
&lt;p&gt;In order to get our domain classes working with DataContext we have to tell DataContext how to map them. We can add mappings in a seperate mapping file, or as attributes. &lt;/p&gt;
&lt;p&gt;Which you prefer is somewhat to personal preference. One tradeoff is between polluting your domain class with mapping information and managing XML files. I have always leaned toward the mapping file, because I like to leave my domain clean of persistence knowldege, others are happy with attributes for what is an orthogonal concern. Here we will show use of attributes. &lt;/p&gt;
&lt;p&gt;One thing to point out here though is that as we are building from our domain first, we have no schema to map to at this point. That&amp;#39;s fine we are going to tag our domain classes for persistence, and then generate the Db from them. &lt;/p&gt;
&lt;p&gt;First we need to identify the table that our domain class maps to. We simply add the Table attribute to our class to do that. [Table] allows us to map to a different name. &lt;/p&gt;
&lt;p&gt;Although there are limitations to mapping (lack of implicit support for many-to-many, single table for inheritance hierachies) working from a clean domain gives us one of the simplest options for using LINQ To SQL as we are defining how to persist our domain, not trying to figure out what domain classes map from an existing schema. Working with a legacy schema with LINQ To SQL will always shape our domain to that schema.&lt;/p&gt;
&lt;p&gt;We do not have an inheritance hierachy, so we don&amp;#39;t need to use the [InheritanceMapping] attribute. &lt;/p&gt;
&lt;p&gt;We need to add this to all of the classes we wish to persist.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Table]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class ITSystem&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Next we tag those fields that we wish to persist as columns. Again we can rename if we don&amp;#39;t like the domain name.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Comments {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name {get;set; }&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Our entities must have an identity, that seperates them from other instances of the class. We need to tag this identity so that we can use it to identify instances of our identity. The Db will use a primary key for this so we tag a column as our primary key.&lt;/p&gt;
&lt;p&gt;We can modify the name property of ITSystem as follows:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(IsPrimaryKey= true)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name {get;set; }&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not all of our fields will be primitives. Where they are instances of another class the Db will need to represent this as a foriegn key pointing to a row in a table to which we persist the other class. We can show this mapping by using the attribute [Association]. We need to tell it how to hook up to our child i.e what property of the child holds the parent identifier. Our Key class looks like this at the minute:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Table]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class Key&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(IsPrimaryKey=true)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string UserName {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Password {get;set; }&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Key() {}&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Key(string userName, string password)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UserName = userName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Password = password;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So we add a SystemName to Key so that we have the child knows its parent, and in instance of the ITSystem System so we can navigatge the relationship bidiectionally. Now we add an Association attribute to ITSystem to indicate how to map the child collection.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Association(OtherKey=&amp;quot;SystemName&amp;quot;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public List&amp;lt;Key&amp;gt; Keys {get;set;}&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And then we can add an Association in Key for the ITSystem so that we can traverse the relationship in both directions.&lt;/p&gt;
&lt;p&gt;Note we need to switch to using&amp;nbsp; EntitySet for the backing storage for the many of side of our associations. We also need to use EntityRef to support the one side of our associations. This supports lazy loading, but pushes a persistence specific class info into our domain. I&amp;#39;m tolerant to this because it can be hidden in the public interface. We only intend to support lazy loading across an aggregate boundary, so from our ITSystem we will lazy load the category, but eager load the Keys. We will use DataLoadOptions to eager load where required. Read the documentation to see the restrictions here. So we end up with this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private EntitySet&amp;lt;Key&amp;gt; keys;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Association(OtherKey=&amp;quot;SystemName&amp;quot;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IList&amp;lt;Key&amp;gt; Keys&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get{return keys;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set{keys.Assign(value);} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Where we have an EntityRef&amp;lt;&amp;gt; or EntitySet&amp;lt;&amp;gt; we need to initialize the collection in the constructor, for example:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;category = default(EntityRef&amp;lt;Category&amp;gt;);&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you are too uncomfortable with using EntityRef and EntitySet see also Mathew Charles&amp;#39;s notes on how to work around this restriction:&amp;nbsp; (&lt;a href="http://blogs.msdn.com/digital_ruminations/archive/2007/08/28/linq-to-sql-poco-support.aspx"&gt;http://blogs.msdn.com/digital_ruminations/archive/2007/08/28/linq-to-sql-poco-support.aspx&lt;/a&gt;) on supporting Persistence Ignorance with LINQ To SQL.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Building the Db&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Once we have all of our classes mapped out, we can generate a Db to support them. I add a utility console project to do this.&lt;/p&gt;
&lt;p&gt;We build a KeySafeContext that looks like this, to help us get generation done. We&amp;#39;ll come back to talk about linking it up to our ISession implementation KeySafeSession.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class KeySafeContext : DataContext&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private const string DbName = &amp;quot;KeySafe&amp;quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Table&amp;lt;ITSystem&amp;gt; Systems { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Table&amp;lt;Key&amp;gt; Keys { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Table&amp;lt;Category&amp;gt; Categories { get; set; }&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Initializes a new instance of the KeySafeContext class.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public KeySafeContext() : base(ConfigurationManager.ConnectionStrings[DbName].ConnectionString)&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Systems = GetTable&amp;lt;ITSystem&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Keys = GetTable&amp;lt;Key&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Categories = GetTable&amp;lt;Category&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;we can then use this with a simple script to build our Db:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class Program&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Generate new version of Db&amp;quot;);&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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; KeySafeContext db = new KeySafeContext();&lt;br /&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; &lt;br /&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; if (db.DatabaseExists())&lt;br /&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; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Deleting old version&amp;quot;);&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; db.DeleteDatabase();&lt;br /&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; }&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&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; db.CreateDatabase();&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&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; Console.WriteLine(&amp;quot;Database created successfully.&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(Exception ex)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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; Console.WriteLine(&amp;quot;Error creating Db...&amp;quot;);&lt;br /&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; Console.WriteLine(ex.Message);&lt;br /&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; throw;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This will pop out any errors for you in your mapping as you build, so its a great way to check that your domain is configured correctly. I certainly got one or two errors when I set this up for the first time.&lt;/p&gt;
&lt;p&gt;Now you can use the generated Db to check how your mappings are coming out. You have a fair amount of flexibility to specify details of how you want your final mapping to look in your attributes. Review the docs. You can use the script above to modify and build until you are happy that your domain model is being mapped out in your preferred form.&lt;/p&gt;
&lt;p&gt;For example the default storage for our strings is nvarchar(4000), which is way larger than we want, so we specify the size and constraints of the columns directly:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(DbType=&amp;quot;NVarChar(50) NOT NULL&amp;quot;, CanBeNull=false, IsPrimaryKey= true)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name {get;set; }&lt;br /&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;I can keep adjusting the metadata in the attributes, and re-generating the Db using the utility until I get something I like.&lt;/p&gt;
&lt;p&gt;This may also be the point where I decide to use an Id field as a key, instead of relying on natural keys, or add a version/timestamp field to support optimistic currency. &lt;/p&gt;
&lt;p&gt;As it is possible that someone might choose to change the names of the systems and categories, I opt to add an Id column and use that as the primary key instead of the name. That change flows through to child objects, which now need to store an Id to represent the foriegn key portion of the association.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(AutoSync = AutoSync.OnInsert, IsDbGenerated = true, IsPrimaryKey = true)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Id { get; set; }&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At the same time I need to adjust the mappings to reflect this. First the association with the Key class:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Association(OtherKey=&amp;quot;SystemId&amp;quot;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IList&amp;lt;Key&amp;gt; Keys {... }&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;and the Key class itself&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Table]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class Key&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(AutoSync = AutoSync.OnInsert, IsDbGenerated = true, IsPrimaryKey = true)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Id { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(DbType=&amp;quot;NVarChar(50) NOT NULL&amp;quot;, CanBeNull=false)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Password { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int SystemId { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private EntityRef&amp;lt;ITSystem&amp;gt; system;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(DbType=&amp;quot;NVarChar(50) NOT NULL&amp;quot;, CanBeNull=false)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string UserName { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Association(OtherKey=&amp;quot;Id&amp;quot;, ThisKey=&amp;quot;SystemId&amp;quot;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public ITSystem System &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get{return system.Entity;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set{system.Entity = value;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;I also decide that as this is intended to be a multi-user system I&amp;#39;m going to support a versions to make optimistic concurrency work better i.e. not through comparing every field.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(AutoSync=AutoSync.Always, IsDbGenerated=true,&amp;nbsp;&amp;nbsp;&amp;nbsp; IsVersion=true)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public byte[] Version {get;set;}&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Finally, where I want the field within the Db to be nullable, I switch to using a nullable type on my domain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Summarizing the Mapping&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Because things may have got a little confusing through all that let&amp;#39;s review the mappings:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Table]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class ITSystem&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int CategoryId { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;private EntityRef&amp;lt;Category&amp;gt; category = default(EntityRef&amp;lt;Category&amp;gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Comments {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(DbType=&amp;quot;NVarChar(50) NOT NULL&amp;quot;, CanBeNull=false)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name {get;set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(AutoSync = AutoSync.OnInsert, IsDbGenerated = true, IsPrimaryKey = true)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Id { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private EntitySet&amp;lt;Key&amp;gt; keys = new EntitySet&amp;lt;Key&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Column(AutoSync=AutoSync.Always, IsDbGenerated=true, IsVersion=true)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public byte[] Version {get;set;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&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; [Association(OtherKey=&amp;quot;SystemId&amp;quot;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IList&amp;lt;Key&amp;gt; Keys&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get{return keys;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbs