<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>There and Back Again : Agile</title><link>http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx</link><description>Tags: Agile</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Old TDD Demo Blog - Digest and Code</title><link>http://blogs.msdn.com/howard_dierking/archive/2008/03/01/old-tdd-demo-blog-digest-and-code.aspx</link><pubDate>Sun, 02 Mar 2008 10:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7986666</guid><dc:creator>hdierking</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/7986666.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=7986666</wfw:commentRss><description>&lt;p&gt;Several of you have emailed me over the past several months asking if I had a copy of the blog text and/or code that I had mentioned in a &lt;a href="http://blogs.msdn.com/howard_dierking/archive/2006/10/29/adventures-in-tdd-ddd-and-nhibernate-from-a-past-life.aspx" mce_href="http://blogs.msdn.com/howard_dierking/archive/2006/10/29/adventures-in-tdd-ddd-and-nhibernate-from-a-past-life.aspx"&gt;much earlier blog entry&lt;/a&gt;.&amp;nbsp; As it turns out, a good friend of mine found some old archived versions of the site on an Internet cache and set them over to me.&amp;nbsp; Therefore, I have taken the web pages and compiled them into an XPS document so that you can see the thought progression that went along with building a small application, TDD style.&amp;nbsp; &lt;/p&gt;  &lt;p&gt;Additionally, I've updated the code samples a bit.&amp;nbsp; Specifically, I've upgraded the version of &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=73818" mce_href="http://sourceforge.net/project/showfiles.php?group_id=73818"&gt;NHibernate to 1.2.1.GA&lt;/a&gt; - and as such, dropped the use of &lt;a href="http://www.ayende.com/projects/nhibernate-query-analyzer/generics.aspx" mce_href="http://www.ayende.com/projects/nhibernate-query-analyzer/generics.aspx"&gt;Ayende's NHibernate Generics library&lt;/a&gt;.&amp;nbsp; Also, as I was going through my NHibernate mappings, I realized that I had been pretty lazy with regard to semantic accuracy for collection types - I had pretty much completely used &amp;lt;bag&amp;gt; mappings instead &amp;lt;set&amp;gt; mappings for unordered collections so that I could use IList&amp;lt;T&amp;gt;.&amp;nbsp; Therefore, I cleaned that up a bit.&amp;nbsp; Other than that, the only other thing that I did was update some of the looping and conditional code to use LINQ.&lt;/p&gt;  &lt;p&gt;Finally, let me emphatically throw out the "Demoware Disclaimer" - The point of the blog and the code samples was to illustrate the thought process and corresponding code behind using TDD to &lt;b&gt;design &lt;/b&gt;a domain model.&amp;nbsp; As a result, everything else in the code is the simplest thing that could be implemented to support the overall goal - and nothing more.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7986666" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/howard_dierking/attachment/7986666.ashx" length="2480294" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Microsoft+.NET+Programming/default.aspx">Microsoft .NET Programming</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Test+Driven+Development/default.aspx">Test Driven Development</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/NHibernate/default.aspx">NHibernate</category></item><item><title>Wow - That Was Annoying</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/11/18/wow-that-was-annoying.aspx</link><pubDate>Mon, 19 Nov 2007 05:18:53 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6385661</guid><dc:creator>hdierking</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/6385661.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=6385661</wfw:commentRss><description>&lt;p&gt;So I'm in an awkward place right now when it comes to programming.&amp;#xA0; In addition to the fact that I no longer program on a day-to-day basis (which is starting to bug me a little more than it used to as I'm afraid I'm starting to atrophy a bit), I'm also now up on Visual Studio 2008 - which is really great in a lot of respects - but at the same time is kind of bumming me out.&amp;#xA0; I'm not bummed because of anything inherent in Visual Studio - I'm bummed because Resharper just doesn't really work all that great in it.&amp;#xA0; Don't get me wrong - R# works - but the semantic analysis tools don't yet work with a lot of the C# 3.0 language enhancements - and as much as I tried to ignore the R# compiler errors on things like Linq queries, I finally just got tired of it an uninstalled R#, impatiently awaiting the 4.0 release.&lt;/p&gt;  &lt;p&gt;Firstly, let me just say that not having R# is miserable from a refactoring standpoint.&lt;/p&gt;  &lt;p&gt;Secondly, losing R# led me down the path to another headache (which is the subject of this post) - I no longer have a VS add-in runner for NUnit.&amp;#xA0; Yes, I know - I could (and probably should) go back and download TD.NET - but instead, I was curious to see how easily it would be for me to just convert my NUnit tests to VS 2008 unit tests.&amp;#xA0; In short, it's not terribly difficult, but getting there was a frustrating journey.&lt;/p&gt;  &lt;p&gt;Why?&amp;#xA0; Because unlike NUnit, where a test fixture is explicit in code (and only in code) via the TestFixture attribute, VS tests rely on a second piece of metadata in order to have them run via the VS test manager/test runner.&amp;#xA0; That metadata is not found in the *.vsmdi file - instead, it's actually a property in the project file of your unit test project.&lt;/p&gt;  &lt;p&gt;Therefore, if you started from a regular class library project and need to have it recognized by VS as a &amp;quot;test project&amp;quot;, open the *.csproj file in notepad and add the following to any PropertyGroup.&lt;/p&gt;  &lt;p&gt;&amp;lt;ProjectTypeGuids&amp;gt;{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}&amp;lt;/ProjectTypeGuids&amp;gt;&lt;/p&gt;  &lt;p&gt;The first Guid identifies your project as a test project (the second is the language I believe - feel free to correct me if I'm wrong).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6385661" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Microsoft+.NET+Programming/default.aspx">Microsoft .NET Programming</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Visual+Studio+2008/default.aspx">Visual Studio 2008</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Test+Driven+Development/default.aspx">Test Driven Development</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/My+Toolbox/default.aspx">My Toolbox</category></item><item><title>ALT.NET - Trip Report</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/10/18/alt-net-trip-report.aspx</link><pubDate>Fri, 19 Oct 2007 06:41:58 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5517391</guid><dc:creator>hdierking</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/5517391.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=5517391</wfw:commentRss><description>&lt;p&gt;I had the recent opportunity to travel to Austin, TX to attend a meeting of the minds of &lt;a href="http://altnetconf.com/participants"&gt;those who are considered thought leaders&lt;/a&gt; in the .NET agile/open source space.&amp;nbsp; This community, in somewhat of an expression of feeling that the general .NET community (as guided by Microsoft) has gone in a different philosophical direction with regard to designing and building software, has aptly elected the name &lt;a href="http://altdotnet.org/"&gt;ALT.NET&lt;/a&gt;.&amp;nbsp; While the meaning of "ALT" was the subject of several spirited debates, my general takeaway is that "ALT" is simply shorthand for "alternatives".&amp;nbsp; The plural is important here because this community is not defining themselves or their values as &lt;strong&gt;the&lt;/strong&gt; alternative to Microsoft technology and guidance.&amp;nbsp; Rather, at the core, they are more interested in trying to promote the development of leaner, more maintainable software using whatever tools are most helpful to those ends (Microsoft or otherwise).&amp;nbsp; To give you an idea of just how big this community's toolbox is, &lt;a href="http://www.flickr.com/photos/palermo/1510489438/in/pool-altnetconf/"&gt;see the following&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Frankly, I think that the choice of the "ALT" moniker, while not meant to be seen as an alternative to Microsoft (which would actually be contradicted by the ".NET" part), is born out of the general frustration by the community that the tools Microsoft gives developers enables short term productivity and long term headaches - while at the same time decreasing the overall skill of developers and making them dependent on a specific type of tool (e.g. - designers).&lt;/p&gt; &lt;p&gt;The conference was conducted in a format called "&lt;a href="http://altnetconf.com/home/open_spaces"&gt;Open Space&lt;/a&gt;".&amp;nbsp; In this style, there were no formal sessions and no formal presenters.&amp;nbsp; Anybody who wanted to talk about (not necessarily lead) any subject could put it forward to the group and schedule it for a time slot/meeting room.&amp;nbsp; As such, &lt;a href="http://simonguest.com/blogs/smguest/default.aspx"&gt;Simon Guest&lt;/a&gt; and I sponsored a talk on how to engage the ALT.NET community with the rest of the .NET developer community.&amp;nbsp; From those individuals who attended the session, we were able to identify a few interesting points of feedback.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The community feels that MSDN and MSDN Magazine are stale and sterile, and that while there are lots of "how-to" articles, there is very little content that explains "why".  &lt;li&gt;There was a general lack of awareness about newer offerings from MSDN online - particularly the architecture dev center.  &lt;li&gt;Many of the audience are already avid and well-followed bloggers, and as such were skeptical as to the value-proposition of writing for MSDN Magazine.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;As to the first 2 points, I think that there is a lot we can do as an organization to incorporate many of the ideas expressed at the ALT.NET conference - for &lt;a href="http://msdn.microsoft.com/msdnmag/"&gt;MSDN Magazine&lt;/a&gt;, the first obvious step is to get more people from this community to write for the magazine - which leads me to the third bullet.&amp;nbsp; The point that I kept reiterating to the participants was that while things like blogging and holding ALT.NET conferences are great, they're an echo chamber.&amp;nbsp; People who visit ALT.NET blogs are generally going there because they have already bought into at least some of the philosophy.&amp;nbsp; If you want to really affect change in the larger community, you need go to the community - and MSDN/MSDN Magazine are 2 fantastic ways to go about it.&amp;nbsp; I think that this message resonated well, as, since returning, I have received several article submissions from conference participants.&lt;/p&gt; &lt;p&gt;In sum, this is a community that really wants to see people develop better software, and it was very encouraging to see Microsoft recognizing their contribution to the community by way of the number of &lt;a href="http://altnetconf.com/participants"&gt;Redmond folks in attendance&lt;/a&gt;.&amp;nbsp; Going forward, it will be exciting to see both how this community evolves - and how their values and practices have an impact on the larger development community.&lt;/p&gt; &lt;p&gt;If you want to know more about the conference, such as the specific sessions/topics, I covered each day of the conference on my blog - so see the following.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://blogs.msdn.com/howard_dierking/archive/2007/10/05/alt-net-conference-opening-day-opening-thoughts.aspx"&gt;Day 1&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/howard_dierking/archive/2007/10/06/alt-net-conference-day-2-taking-the-good-with-the-bad.aspx"&gt;Day 2&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/howard_dierking/archive/2007/10/18/alt-net-day-3.aspx"&gt;Day 3&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://www.flickr.com/groups/altnetconf/pool/"&gt;Click here for pictures&lt;/a&gt; from the conference.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5517391" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Test+Driven+Development/default.aspx">Test Driven Development</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/MSDN+Magazine/default.aspx">MSDN Magazine</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/ALTNETCONF/default.aspx">ALTNETCONF</category></item><item><title>ALT.NET - Day 3</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/10/18/alt-net-day-3.aspx</link><pubDate>Fri, 19 Oct 2007 04:43:06 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5516546</guid><dc:creator>hdierking</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/5516546.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=5516546</wfw:commentRss><description>&lt;p&gt;I can't believe that it has taken me so long to get around to writing my concluding thoughts on the conference.&amp;nbsp; That said, perhaps this is a good thing as I have been able to watch the post-conference churn in the blogosphere over the past couple of weeks and can incorporate some of my thoughts on that into my more general thoughts on the conference and on ALT.NET.&lt;/p&gt; &lt;p&gt;Also, in the spirit of being transparent, I will follow this post with a "Trip Report" post.&amp;nbsp; This will be the (verbatim) summary email that I'm sending out to my management - so if you're curious about "what is being said internally at Microsoft about the conference and ALT.NET?", there you go.&lt;/p&gt; &lt;h3&gt;First Things First - Day 3&lt;/h3&gt; &lt;h5&gt;Session - Engaging with the Community (aka - the Simon and Howard show&amp;lt;g&amp;gt;)&lt;/h5&gt; &lt;p&gt;&lt;a href="http://simonguest.com/blogs/smguest/default.aspx"&gt;Simon Guest&lt;/a&gt;, owner of the &lt;a href="http://msdn2.microsoft.com/en-us/arcjournal/default.aspx"&gt;MS Architect Journal&lt;/a&gt;, and I held a session to discuss how the ALT.NET community could engage with the larger .NET community in a way that is practical, tangible, and generally more helpful than the approaches thus far (for an example of what I'm contrasting &lt;em&gt;more&lt;/em&gt; to, see &lt;a href="http://blogs.msdn.com/howard_dierking/archive/2007/10/06/alt-net-conference-day-2-taking-the-good-with-the-bad.aspx"&gt;my post on day 2 of the conference&lt;/a&gt;).&amp;nbsp; Firstly, many thanks to Simon for being much more detail oriented than I am.&amp;nbsp; Using the dry erase board, Simon captured and related the major points expressed by the session participants.&amp;nbsp; This was the perfect complement (or supplement, depending on how you want to look at it) to my style, which is much more of an extended conversation.&lt;/p&gt; &lt;p&gt;Anyway, the basic point that I came into the conversation hoping to convey was (and remains) very simple.&amp;nbsp; While things like blogging and holding ALT.NET conferences are great, it's an echo chamber.&amp;nbsp; People that visit ALT.NET blogs are generally going there because they have already bought into at least some of the philosophy.&amp;nbsp; If you want to really affect change in the larger community, you need go to the community - and &lt;a href="http://msdn.microsoft.com/"&gt;MSDN&lt;/a&gt;/&lt;a href="http://msdn.microsoft.com/msdnmag"&gt;MSDN Magazine&lt;/a&gt; are 2 fantastic ways to go about it.&lt;/p&gt; &lt;p&gt;All in all, I think that there was a very positive response from everybody who attended the session - and I have gotten several emails from people who have taken me up on my challenge to submit article ideas for the magazine.&lt;/p&gt; &lt;h5&gt;Session - Language Oriented Programming&lt;/h5&gt; &lt;p&gt;I now feel like an adult developer - I've gotten into an argument with &lt;a href="http://codebetter.com/blogs/scott.bellware/"&gt;Scott Bellware&lt;/a&gt; &amp;lt;g&amp;gt;.&amp;nbsp; So those of you who know me know that I'm kind of a language geek - &lt;a href="http://intentsoft.com/company/management.html"&gt;Charles Simonyi&lt;/a&gt; is my hero.&amp;nbsp; As such, I was really excited to be part of a discussion on what I thought would be in that vein - and needless to say, I was disappointed when Scott seemed to only want to talk about the philosophical ramifications of doing away with parentheses for method calls in Ruby.&amp;nbsp; I remember having similar conversations wrt JavaScript about 5 years ago!&lt;/p&gt; &lt;p&gt;On a positive note, though, I wasn't alone in my thinking - and a side conversation on language oriented programming got started and actually continued after the meeting ended.&amp;nbsp; Several issues were discussed, but a couple interesting ones that jumped out at me were the following.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Language oriented programming is defined along somewhat of a continuum - the continuum is measured by the definition of language and ranges from defining language as a soluble code library to defining language as a full blown DSL.&amp;nbsp; Depending on your definition, the proximity for the realization of language oriented programming shifts.  &lt;li&gt;We will probably go way too far in implementing custom "languages" before we figure out the best practices - then pragmatism will drive things back to the center (sound familiar?)  &lt;li&gt;In the case of DSL, there are 2 major challenges  &lt;ul&gt; &lt;li&gt;Keeping the language scoped to a narrow domain - the biggest mistake for a DSL creator is letting it grow into another Turing-complete GPL.  &lt;li&gt;The language integration/collaboration strategy.&amp;nbsp; I am personally REALLY interested in this one.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h5&gt;Closing Session&lt;/h5&gt; &lt;p&gt;I shook everybody's hand on a piece of silly puddy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5516546" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/MSDN+Magazine/default.aspx">MSDN Magazine</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/ALTNETCONF/default.aspx">ALTNETCONF</category></item><item><title>Note to My ALT.NET Friends Submitting Article Ideas</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/10/18/note-to-my-alt-net-friends-submitting-article-ideas.aspx</link><pubDate>Fri, 19 Oct 2007 02:05:13 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5514842</guid><dc:creator>hdierking</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/5514842.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=5514842</wfw:commentRss><description>&lt;p&gt;I'm glad that I'm obsessive enough to periodically check my junk folder in Outlook.&amp;nbsp; As I was doing this today, I found emails from &lt;a href="http://codebetter.com/blogs/jeremy.miller/default.aspx"&gt;Jeremy&lt;/a&gt; and &lt;a href="http://geekswithblogs.net/coredump/Default.aspx"&gt;Russell&lt;/a&gt; about writing for &lt;a href="http://msdn.microsoft.com/msdnmag/"&gt;MSDN Magazine&lt;/a&gt;.&amp;nbsp; I was able to catch these and respond - however, if you submitted an article to me a while back and have not heard from me, it may have very well ended up accidentally getting trashed.&amp;nbsp; Therefore, please resend to &lt;a href="mailto:mmsubmit@microsoft.com"&gt;mmsubmit@microsoft.com&lt;/a&gt; (this is our official alias for content submission anyway).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5514842" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/MSDN+Magazine/default.aspx">MSDN Magazine</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/ALTNETCONF/default.aspx">ALTNETCONF</category></item><item><title>Free PDF "Quick Version" of Domain Driven Design</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/10/10/free-pdf-quick-version-of-domain-driven-design.aspx</link><pubDate>Wed, 10 Oct 2007 20:56:47 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5392801</guid><dc:creator>hdierking</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/5392801.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=5392801</wfw:commentRss><description>&lt;p&gt;&lt;a title="http://www.infoq.com/minibooks/domain-driven-design-quickly" href="http://www.infoq.com/minibooks/domain-driven-design-quickly"&gt;http://www.infoq.com/minibooks/domain-driven-design-quickly&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5392801" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category></item><item><title>ALT.NET Conference, Day 2 - Taking the Good With the Bad</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/10/06/alt-net-conference-day-2-taking-the-good-with-the-bad.aspx</link><pubDate>Sun, 07 Oct 2007 07:57:27 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5331457</guid><dc:creator>hdierking</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/5331457.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=5331457</wfw:commentRss><description>&lt;p&gt;Today's post is actually a nice continuance of yesterday's because it deals very specifically with one of the issues that I raised yesterday - specifically the issue of the emerging tenuous relationship between the ALT.NET community and the rest of the professional .NET developer community.&amp;nbsp; That said, today was fantastic - great people, great discussions - and a great show of forthcoming technology by &lt;a href="http://weblogs.asp.net/scottgu/default.aspx"&gt;ScottGu&lt;/a&gt;.&amp;nbsp; So, in sum, we'll deal with the good and the not so good in tonight's post (IMHO &amp;lt;g&amp;gt;)!&lt;/p&gt; &lt;h4&gt;The Not So Good - How to Be a Catalyst for Change In the Community&lt;/h4&gt; &lt;p&gt;I went into this session hoping that individuals would come in wanting to share success and/or failure stories related to creating an environment that bought into at least some of the principles of agile - or at the very least became more passionate about writing great software.&amp;nbsp; I also went in expecting there to be a fair amount of Microsoft bashing because of designers, code generation, NIH, etc... (I would mention MSDN/&lt;a href="http://msdn.microsoft.com/msdnmag/"&gt;MSDN Magazine&lt;/a&gt; here, but that session is tomorrow, so I'll deal with that in the morning).&amp;nbsp; What actually unfolded actually surprised me a bit.&amp;nbsp; So firstly, I should say that there were some success stories shared.&amp;nbsp; &lt;a href="http://www.jpboodhoo.com/blog/"&gt;J.P. Boodhoo&lt;/a&gt; talked about some of the successes he has had with "lunch &amp;amp; learns" - &lt;a href="http://www.hanselman.com/blog/"&gt;Scott Hanselman&lt;/a&gt; and &lt;a href="http://jayflowers.com/joomla/"&gt;Jay Flowers&lt;/a&gt; talked about growing influence exponentially via a style that for this post we'll call "influencing the influencers" (Jay - you had mentioned a book that dealt with this topic - if you're reading, please post the title in the comments).&amp;nbsp; Past those (and a few other) examples, though, the conversation took what I considered a fairly cynical and elitist turn.&amp;nbsp; Earlier I mentioned that I was surprised a bit by what unfolded.&amp;nbsp; What surprised me was that the frustration expressed was not as much directed at Microsoft, but was directed at the general development community.&amp;nbsp; It basically came across as "why won't all these people stop calling me dogmatic and listen to what I'm trying to tell them?!?"&amp;nbsp; Several in the room made the argument that energy should only be expended on influencing those who wanted to be influenced.&amp;nbsp; Huh??&amp;nbsp; If they...want to be influenced....doesn't that already....nevermind.&amp;nbsp; Anyway, I basically came away from that session with 2 concluding saddening thoughts about many in the ALT.NET community.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;They will always be 10 steps ahead of the rest of the professional development community because they are incredibly smart, talented, and motivated.&lt;/li&gt; &lt;li&gt;They will always be frustrated because they are narcissistic.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;OK - maybe it was because I drank more coffee, maybe it was something else, but the day got much better as it progressed.&amp;nbsp; Let's move on.&lt;/p&gt; &lt;h4&gt;The Good - DSLs/NHibernate&lt;/h4&gt; &lt;p&gt;I'm grouping these together because I walked in half way through the &lt;a href="http://en.wikipedia.org/wiki/Domain-specific_programming_language"&gt;DSL&lt;/a&gt; talk and I just didn't take that many notes from the &lt;a href="http://www.hibernate.org/343.html"&gt;NHibernate&lt;/a&gt; talk.&amp;nbsp; In fact, I think I'm just going to do bullet points here.&lt;/p&gt; &lt;h5&gt;DSL&lt;/h5&gt; &lt;ul&gt; &lt;li&gt;I hadn't realized that Microsoft &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/10/03/releasing-the-source-code-for-the-net-framework-libraries.aspx"&gt;released the source code for the .NET Framework Class Library&lt;/a&gt;.&amp;nbsp; Totally cool - especially since, as ScottGu mentioned, they shipped it with the symbols, so profiling and debugging into the framework itself is now simple.&lt;/li&gt; &lt;li&gt;There was a lot of talk about DSL support in Ruby.&amp;nbsp; I haven't worked in Ruby so I really can't speak to this - but now I'm curious.&lt;/li&gt; &lt;li&gt;One really interesting comment that ScottGu made, regarding DSLs is to make sure that you have mastered your GPL first, as this will provide you the best platform from which to jump into DSLs.&lt;/li&gt;&lt;/ul&gt; &lt;h5&gt;NHibernate&lt;/h5&gt; &lt;ul&gt; &lt;li&gt;It was tough to blur the lines between where we crossed into a general &lt;a href="http://www.domaindrivendesign.org/"&gt;DDD&lt;/a&gt; discussion and when we were still talking about NHibernate - particularly when we were discussing architectural patterns for DALs, etc...&lt;/li&gt; &lt;li&gt;To the NHibernate team (or someone with the time to look at this on the forge) - It would be totally cool if we could get JIT loading of HBMs, or at least have the option to suppress fail-fast when building the session factory.&amp;nbsp; This came out of a discussion where many in the group were expressing the pain felt when one invalid HBM file caused every unit test to fail (or nearly every view to crash) because the session factory couldn't be created.&lt;/li&gt; &lt;li&gt;On that note, a MSBuild/NAnt HBM validator build task would be nice for plugging into the build.&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;The Rockin' - ScottGu's Show and Tell&lt;/h4&gt; &lt;p&gt;So I haven't really had a lot of exposure to MVC in web applications (yes, I have let the whole RoR phenomenon pass me by - for shame, I know).&amp;nbsp; And as a result, I really didn't see the point of the whole paradigm shift to MVC.&amp;nbsp; I did DVC in MFC and it was a pain - so perhaps I was just avoiding the topic because of past aches, but for whatever reason, this was all new to me.&amp;nbsp; So anyways, Scott demonstrated the new MVC framework that will be available in CTP form pretty soon.&amp;nbsp; Honestly, it's pretty cool.&amp;nbsp; I don't really buy into the argument that MVC is absolutely necessary to cleanly separate the logical layers of your application.&amp;nbsp; I have been doing DDD for a while now and have never run into a major problem with bleeding of concerns on web projects - but maybe that's just me.&amp;nbsp; However, if you're into having leaner, better controlled HTML and, more intuitive URLs, and reduced &lt;em&gt;probability&lt;/em&gt; for concern-bleed, the MVC framework is definitely the way to go.&lt;/p&gt; &lt;p&gt;On a related note, let the record show that &lt;a href="http://codebetter.com/blogs/scott.bellware/"&gt;Scott Bellware&lt;/a&gt; is officially my favorite heckler.&amp;nbsp; Scott - whenever you're in Redmond, the drinks are on me!&lt;/p&gt; &lt;p&gt;Back to the MVC discussion, my main next action is to see if I can actually find the bits so that I can get up to speed a bit.&amp;nbsp; Who knows, maybe I'll even take the approach of one of my close friends at P&amp;amp;P and buy a Macbook Pro to play with RoR &amp;lt;g&amp;gt;!&lt;/p&gt; &lt;h4&gt;The Confused - DDD&lt;/h4&gt; &lt;p&gt;So since this post is getting long, I'm going to sum this session up with a pretty simple statement.&amp;nbsp; &lt;strong&gt;&lt;a href="http://www.domaindrivendesign.org/about/index.html#eric"&gt;Eric&lt;/a&gt; - A little help please? &lt;/strong&gt; There continues to be a great deal of confusion and disagreement in the DDD community about some very fundamental concepts.&amp;nbsp; Examples include the definition of a domain service, an application service, and the very distinctive characterics of DDD that make it different than simply good OOP heuristics.&lt;/p&gt; &lt;p&gt;On a closing note, I have never seen so many iPhones in one place.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5331457" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Visual+Studio+2008/default.aspx">Visual Studio 2008</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/MSDN+Magazine/default.aspx">MSDN Magazine</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Events/default.aspx">Events</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/ALTNETCONF/default.aspx">ALTNETCONF</category></item><item><title>ALT.NET Conference - Opening Day..Opening Thoughts</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/10/05/alt-net-conference-opening-day-opening-thoughts.aspx</link><pubDate>Sat, 06 Oct 2007 08:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5307327</guid><dc:creator>hdierking</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/5307327.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=5307327</wfw:commentRss><description>&lt;P&gt;I'm currently in Austin, Texas where I'm attending the &lt;A href="http://www.altnetconf.com/home" mce_href="http://www.altnetconf.com/home"&gt;ALT.NET conference&lt;/A&gt;.&amp;nbsp; This conference is essentially a who's who of thought leaders in the .NET agile/open source community - everyone from &lt;A href="http://martinfowler.com/" mce_href="http://martinfowler.com/"&gt;Martin Fowler&lt;/A&gt; to &lt;A href="http://jamesnewkirk.typepad.com/posts/" mce_href="http://jamesnewkirk.typepad.com/posts/"&gt;Jim Newkirk&lt;/A&gt; to &lt;A href="http://www.hanselman.com/blog/" mce_href="http://www.hanselman.com/blog/"&gt;Scott Hanselman&lt;/A&gt; to &lt;A href="http://codebetter.com/blogs/scott.bellware/" mce_href="http://codebetter.com/blogs/scott.bellware/"&gt;Scott Bellware&lt;/A&gt; - the list goes on and on.&amp;nbsp; In sum, over half of the people that you wanted &lt;A href="http://blogs.msdn.com/howard_dierking/archive/2007/08/28/who-do-you-want-to-read.aspx" mce_href="http://blogs.msdn.com/howard_dierking/archive/2007/08/28/who-do-you-want-to-read.aspx"&gt;listed as wanting to hear from&lt;/A&gt; in MSDN Magazine are attending this conference.&lt;/P&gt;
&lt;P&gt;The conference is being conducted in a format called &lt;A href="http://www.altnetconf.com/home/open_spaces" mce_href="http://www.altnetconf.com/home/open_spaces"&gt;Open Spaces&lt;/A&gt;.&amp;nbsp; This is one of the coolest things that I've ever seen in conferences.&amp;nbsp; Basically, after a brief round of introductions, we launched into tonight's main activity - determining the schedule for the remainder of the conference.&amp;nbsp; On a whiteboard was a 2-dimensional matrix - available rooms on the y-axis; time slots on the x-axis.&amp;nbsp; Anybody that had an idea for a session wrote down the idea on a post-it note, presented it to the group, and placed it into a time slot.&amp;nbsp; Once all the slots had been filled additional ideas were placed in a general holding space.&amp;nbsp; Once all the ideas were collected, every individual marked which sessions they were interested in attending and based on this feedback, the schedule was renegotiated.&amp;nbsp; It's worth pointing out that in this type of conference, there is no distinction between presenter and attendee.&amp;nbsp; Everyone just shows up to whatever they are interested in.&amp;nbsp; If you aren't interested in a session, get up and go.&amp;nbsp; If you get sucked into a conference in the hallway - cool.&amp;nbsp; It's incredibly exciting.&lt;/P&gt;
&lt;P&gt;So there were 2 comments that I thought were really noteworthy/funny in tonight's opening session.&amp;nbsp; The first was as follows.&lt;/P&gt;
&lt;P&gt;"The values support the tools."&lt;/P&gt;
&lt;P&gt;I'm not sure I buy this.&amp;nbsp; I think that the values support the tools if you have values that make you interested in values.&amp;nbsp; I think that many developers are perfectly content with using whatever tools they are presented with (e.g. - not going in search of 'better' tools) to do the job that they are being paid to do - solve the problems that they are being paid to solve.&amp;nbsp; I'm not trying to make a value judgement on this group of developers (though I admit, it does kind of sound that way).&amp;nbsp; At the same time, I believe that this is a reality, and as such, focusing on 'instilling values' is not the approach to take if the goal is to change behavior.&amp;nbsp; I imagine that this theme will reoccur throughout this weekend.&amp;nbsp; And that leads us to the second notable quote - ala Scott Hanselman.&lt;/P&gt;
&lt;P&gt;"Mort is crying because mommy and daddy are fighting."&lt;/P&gt;
&lt;P&gt;So in case you missed all of the conversations from last year on the blogosphere, &lt;A href="http://www.nikhilk.net/Personas.aspx" mce_href="http://www.nikhilk.net/Personas.aspx"&gt;Mort is the Microsoft persona&lt;/A&gt; to describe the group that I talked about in the previous paragraph.&amp;nbsp; Unfortunately, Mort has become somewhat of a derogatory term as of late since he is used more as an accusatory glass that different communities and Microsoft throw at one another when arguing over products, methodologies, etc... you know - 'values'.&amp;nbsp; As a result, Mort is sitting quietly on the sidelines wondering why Microsoft and it's community thought leaders can't get along - and he here's his name mentioned in so many arguments, he wonders "could it be me?"&lt;/P&gt;
&lt;P&gt;Why do I care about this?&amp;nbsp; Because I love agile - I love DDD, TDD, BDD, patterns, NHibernate, R#, et al.&amp;nbsp; And I want to introduce more and more of this type of content into MSDN Magazine.&amp;nbsp; However, I think that many of you who read the magazine are not as zealous in programming ideology as many here at the conference - and that's ok.&amp;nbsp; What I refuse to do is allow the magazine to become a forum for the next religious war - to basically take the "C++ rules - VB sucks" argument and turn it into "ALT rocks - Mort sucks".&amp;nbsp; So, for those of you who want more content on all of the cool agile things mentioned above, me too.&amp;nbsp; For those of you who don't care about all of the ideology, that's cool too.&amp;nbsp; I am interested in seeing MSDN Magazine provide practical solutions to all of its readers, no matter where they are on the programmer continuum.&amp;nbsp; I think that a strong case can be made for many of the tools/methods in the agile space - and I want to present them in the Magazine in a way that provides a real incentive for using them.&amp;nbsp; That incentive?&amp;nbsp; Making programming easier and more enjoyable - not buying into a set of values.&lt;/P&gt;
&lt;P&gt;Until tomorrow...&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5307327" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/MSDN+Magazine/default.aspx">MSDN Magazine</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Events/default.aspx">Events</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/ALTNETCONF/default.aspx">ALTNETCONF</category></item><item><title>DSLs - Not Quite Child's Play ... But Closer!</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/05/16/dsls-not-quite-child-s-play-but-closer.aspx</link><pubDate>Wed, 16 May 2007 20:53:33 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2677471</guid><dc:creator>hdierking</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/2677471.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=2677471</wfw:commentRss><description>&lt;p&gt;One of the books I've been reading recently Jack Greenfield's (and several other really smart people) book &lt;a href="http://www.amazon.com/o/ASIN/0471202843/ref=s9_asin_image_2-2288_p/102-5904142-8869700?pf_rd_m=ATVPDKIKX0DER&amp;amp;pf_rd_s=center-2&amp;amp;pf_rd_r=09ZBKEZNTZ3FESHEGV5Q&amp;amp;pf_rd_t=101&amp;amp;pf_rd_p=288448501&amp;amp;pf_rd_i=507846"&gt;Software Factories&lt;/a&gt;.&amp;nbsp; While I'm not yet sure that I buy into the notion that the creation of software solutions will undergo an &lt;a href="http://en.wikipedia.org/wiki/Industrial_revolution"&gt;industrial revolution&lt;/a&gt; of sorts (at least in a measurable timeframe), the thing that really drove me to this book was the discussion on domain specific languages - or "little languages" if you're coming from the UNIX world.&amp;nbsp; I've been following the efforts on DSL coming out of companies such as &lt;a href="http://msdn2.microsoft.com/en-us/vstudio/aa718368.aspx"&gt;Microsoft&lt;/a&gt;, &lt;a href="http://www.jetbrains.com/mps/"&gt;JetBrains&lt;/a&gt;, and &lt;a href="http://www.intentionalsoftware.com/"&gt;Intentional Software&lt;/a&gt; for a while now and while I think that &lt;a href="http://www.martinfowler.com/bliki/ModelDrivenArchitecture.html"&gt;model driven architecture&lt;/a&gt; is probably too prescriptive as an approach, I do think that there is a great deal of business value to be gained by promoting &lt;a href="http://www.onboard.jetbrains.com/is1/articles/04/10/lop/"&gt;language oriented programming&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;While Jack's book is incredibly insightful, it also (at least for me) can be a pretty difficult read as it takes me back&amp;nbsp;to my old CS days.&amp;nbsp; In fact, much of the work on DSLs reads this way as we are just now starting to try and describe and articulate the theory behind the tools.&amp;nbsp; Therefore, I think it's always fun to see a practical implementation of a "little language".&lt;/p&gt; &lt;p&gt;The &lt;a href="http://web.mit.edu/newsoffice/2007/resnick-scratch.html"&gt;Scratch language&lt;/a&gt; is a visual programming language for kids developed by Mitchel Resnick and team at &lt;a href="http://www.media.mit.edu/"&gt;MIT's Media Lab&lt;/a&gt;.&amp;nbsp; The language allows kids to build software systems that do some very basic - but very real things.&amp;nbsp; What's cool is to think about&amp;nbsp;the next step - when we come to a better understanding of integrating different DSLs to create richer systems.&amp;nbsp; As an example, taking a Scratch application and integrating it into a distribution language would be an easy leap for allowing kids to create simple games that they can immediately promote to the Internet to play with other kids all over the world!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2677471" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Visual+Studio+Team+System/default.aspx">Visual Studio Team System</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category></item><item><title>NHibernate Custom Mapping Types</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/04/23/nhibernate-custom-mapping-types.aspx</link><pubDate>Tue, 24 Apr 2007 05:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2254247</guid><dc:creator>hdierking</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/2254247.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=2254247</wfw:commentRss><description>&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;(originally posted to &lt;A href="http://blogs.sarkhouston.com/hdierking/" target=_blank mce_href="http://blogs.sarkhouston.com/hdierking/"&gt;Absolute Opinion&lt;/A&gt; on June 14, 2006) 
&lt;P&gt;As you should know by now, NHibernate is an object-relational mapping (ORM) tool that uses XML metadata files to marshal data between an object-oriented domain model and a relational database. Now, in the majority of use cases, the default support provided by NHibernate will be sufficient for saving and fetching your domain objects. However, there are cases where additional capabilities are required. Fortunately, NHibernate provides lots of extension points. I’m going to discuss 2 scenarios in this article – both of which take advantage of creating custom NHibernate mapping types. 
&lt;P&gt;&lt;B&gt;Scenario 1:&lt;/B&gt; 
&lt;P&gt;You have an implementation of the &lt;A href="http://www.ksc.com/article3.htm" mce_href="http://www.ksc.com/article3.htm"&gt;Type Object Pattern&lt;/A&gt;. Simply put, you have a class to represent the type of an object, and then a class the references your type object. The static model looks like the following. 
&lt;P&gt;&lt;IMG src="http://intranet.sarkhouston.com/intranet/code/Code%20Samples/hdierking_blog/TypeObjectStaticDiagram.gif" mce_src="http://intranet.sarkhouston.com/intranet/code/Code%20Samples/hdierking_blog/TypeObjectStaticDiagram.gif"&gt; 
&lt;P&gt;Now, let’s take this a step further and say that your type class takes a pretty large amount of time to construct and initialize. Therefore, you decide to implement a &lt;A href="http://www.dofactory.com/Patterns/PatternFlyweight.aspx" mce_href="http://www.dofactory.com/Patterns/PatternFlyweight.aspx"&gt;flyweight factory&lt;/A&gt; in order to minimize the performance impact on your application in terms of the number of type class instances that must be constructed. Fantastic! Now, let’s look at the ramifications on persistence. 
&lt;P&gt;From the object persistence perspective, the problem you are now facing is that you do not want to persist the object state for your TypeClass instance (since you are trying to control the number of instances for that class). However, you do want to persist enough information about the TypeClass instance so that when you load an instance of ActualClass from the database, you can get the correct TypeClass instance from the flyweight factory and apply it to your reconstructed ActualClass instance. 
&lt;P&gt;Now in a world without NHibernate (oh what a sad world!), we would create a data access class for ActualClass and add methods for setting and fetching ActualClass instances. Since the TypeClass reference exists outside of the database scope, we would add the association in the data access class. For example, your data access class may have code that looks like the following.&amp;nbsp;&amp;nbsp; 
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; ActualClassRepository {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;  &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; Save(ActualClass actualClass) {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;    IDbCommand cmd = &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;    IDbDataParameter param;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;//build the sql command and parameters...&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;    param = cmd.CreateParameter();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt;    param.ParameterName = &lt;SPAN class=str&gt;"@typeClass"&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt;    param.DbType = DbType.String;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;    param.Value = actualClass.Type.Name;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;  }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;  &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; ActualClass Get(&lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; id) {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;    IDataReader rdr = &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  15:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  16:  &lt;/SPAN&gt;    &lt;SPAN class=rem&gt;//build the sql command to and get a data reader...&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  17:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (rdr.Read()) {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  18:  &lt;/SPAN&gt;      ActualClass ret = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; ActualClass();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  19:  &lt;/SPAN&gt;      ret.Data = rdr.GetString(0);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  20:  &lt;/SPAN&gt;      TypeClassFactory factory = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; TypeClassFactory();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  21:  &lt;/SPAN&gt;      ret.Type = factory.GetTypeClass(rdr.GetString(1));&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  22:  &lt;/SPAN&gt;    }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  23:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  24:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  25:  &lt;/SPAN&gt;  }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  26:  &lt;/SPAN&gt;}&lt;/PRE&gt;&lt;/DIV&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;P&gt;If you pay attention to the code shown in bold for both the get and set methods, you can see how your data access class might handle the setting and fetching of an object and its associated type object. When saving the ActualClass object, the data access object saves the name of the associated TypeClass object to the database. When the ActualClass object is restored from the database, the name of the TypeClass is retrieved and passed to our flyweight factory where the object instance can be acquired and set on the ActualClass object being built. 
&lt;P&gt;Now, this works fine in very simple cases like the one mentioned above. However, most object models have many more complex sets of associations. It is in cases like this where NHibernate reveals a great deal of strength – and it would be advantageous to be able to use NHibernate to solve our type object problem. 
&lt;P&gt;Enter the custom mapping type. 
&lt;P&gt;In NHibernate, a custom mapping type is a class that derives from either the IUserType or ICompositeUserType interfaces. These interfaces contain several methods that must be implemented, but for our purposes here, we’re going to focus on 2 of them. Consider the following.&amp;nbsp;&amp;nbsp; 
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; TypeClassUserType : IUserType&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;  ...&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;  &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; IUserType.NullSafeGet(IDataReader rs, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;[] names, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; owner) {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; name = NHibernateUtil.String.NullSafeGet(rs, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;      names[0]) &lt;SPAN class=kwrd&gt;as&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;    TypeClassFactory factory = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; TypeClassFactory();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;    TypeClass typeobj = factory.GetTypeClass(name);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  15:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; typeobj;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  16:  &lt;/SPAN&gt;  }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  17:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  18:  &lt;/SPAN&gt;  &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; IUserType.NullSafeSet(IDbCommand cmd, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  19:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;value&lt;/SPAN&gt;, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  20:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; index) {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  21:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  22:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; name = ((TypeClass)&lt;SPAN class=kwrd&gt;value&lt;/SPAN&gt;).Name;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  23:  &lt;/SPAN&gt;    NHibernateUtil.String.NullSafeSet(cmd, name, index);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  24:  &lt;/SPAN&gt;  }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  25:  &lt;/SPAN&gt;}&lt;/PRE&gt;&lt;/DIV&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;P&gt;Having created this class, I can now explicitly map the association between ActualClass and TypeClass as a simple property on the ActualClass mapping.&lt;PRE class=csharpcode&gt;&amp;lt;property
  name=&lt;SPAN class=str&gt;"Type"&lt;/SPAN&gt;
  column=&lt;SPAN class=str&gt;"TypeName"&lt;/SPAN&gt;
  type=&lt;SPAN class=str&gt;"Samples.NHibernate.DataAccess.TypeClassUserType, 
    Samples.NHibernate.DataAccess"&lt;/SPAN&gt; /&amp;gt;&lt;/PRE&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;P&gt;As NHibernate is in the process of saving an instance of ActualType, it will load and create a new instance of TypeClassUserType and call the NullSafeSet method. As you can see from the method body, I am simply extracting the name from the mapped property (passed in as the value parameter) and setting the extracted name as the value of the parameter to be set in the database. The net result is that although the Type property of ActualClass is TypeClass in the domain model, only the Name property of the TypeClass object gets stored in the database. The converse is also true. When NHibernate is loading an instance of ActualType from the database and the finds a property of my custom mapping type, it loads my custom type and calls the NullSafeGet method. As you can see, my method gets the name from the returned data, calls my flyweight factory to get the correct instance of TypeClass, and then actually returns that instance. The type resolution process happens transparently to my data access classes (and even to NHibernate itself for that matter). 
&lt;P&gt;&lt;B&gt;Scenario 2:&lt;/B&gt; 
&lt;P&gt;As a part of your object model, you have a standard IDictionary implementation (Oh my goodness – untyped collections!!! Yea – it still happens sometimes!) that looks as follows.&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt; IDictionary _values = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Hashtable();&lt;/PRE&gt;
&lt;P&gt;Now, here’s the basic problem with this implementation when persisting to a database. By design, this data structure can contain – well – anything. So how do you persist it to the database in a meaningful way? One technique that can be used is to store the value as a string in one column and store the type identifier as a string in a different column. The problem here is that many times (especially when you think about it from the database point of view) you end up with a clunky object model because there is no real reason to store the type as an additional piece of data. Fundamentally, the database requires 2 pieces of information to make sense of 1 piece of domain model information (value + type). It would be really great if we could hide this splitting and merging of data in the mapping layer… 
&lt;P&gt;…and we can – using a composite custom mapping type. Take a look at the following. 
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; Object2StringUserType : ICompositeUserType&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;  ...&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;  &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; ICompositeUserType.NullSafeGet(IDataReader dr, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;[] names, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt;    ISessionImplementor session, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; owner) {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; val = (&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;) NHibernateUtil.String.NullSafeGet(dr, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;      names[0], &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;      session, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;      owner);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  15:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  16:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; valTypeString = &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  17:  &lt;/SPAN&gt;      (&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;) NHibernateUtil.String.NullSafeGet(dr, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  18:  &lt;/SPAN&gt;        names[1], &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  19:  &lt;/SPAN&gt;        session, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  20:  &lt;/SPAN&gt;        owner);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  21:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  22:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (val == &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt; || valTypeString == &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;)&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  23:  &lt;/SPAN&gt;      &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  24:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  25:  &lt;/SPAN&gt;    Type valType = Type.GetType(valTypeString);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  26:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; TypeDescriptor.GetConverter(valType).ConvertFrom(val);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  27:  &lt;/SPAN&gt;  }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  28:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  29:  &lt;/SPAN&gt;  &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; ICompositeUserType.NullSafeSet(IDbCommand cmd, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  30:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;value&lt;/SPAN&gt;, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  31:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; index, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  32:  &lt;/SPAN&gt;    ISessionImplementor session) {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  33:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  34:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; valString = TypeDescriptor.GetConverter(&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  35:  &lt;/SPAN&gt;      &lt;SPAN class=kwrd&gt;value&lt;/SPAN&gt;.GetType()).ConvertToString(&lt;SPAN class=kwrd&gt;value&lt;/SPAN&gt;);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  36:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  37:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; valTypeString = &lt;SPAN class=kwrd&gt;value&lt;/SPAN&gt;.GetType().AssemblyQualifiedName;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  38:  &lt;/SPAN&gt;    NHibernateUtil.String.NullSafeSet(cmd, valString, index, session);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  39:  &lt;/SPAN&gt;    NHibernateUtil.String.NullSafeSet(cmd, &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  40:  &lt;/SPAN&gt;      valTypeString, index + 1, session);&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  41:  &lt;/SPAN&gt;  }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  42:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  43:  &lt;/SPAN&gt;  &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;[] ICompositeUserType.PropertyNames {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  44:  &lt;/SPAN&gt;    get { &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;[] {&lt;SPAN class=str&gt;"val"&lt;/SPAN&gt;, &lt;SPAN class=str&gt;"valType"&lt;/SPAN&gt;}; }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  45:  &lt;/SPAN&gt;  }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  46:  &lt;/SPAN&gt;}&lt;/PRE&gt;&lt;/DIV&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;P&gt;As you can see, this interface fragment looks similar to that of our regular custom mapping type. However, it has several additional members which allow the custom type to actually map a given domain model value onto multiple database columns. In this example, I have used the type to split the value of my IDictionary object over 2 columns in my database table: Value and ValueType. When my dictionary is persisted, my mapping type converts the dictionary value to a string and then persists that value along with the fully qualified name of the value’s original type to 2 columns in the database. Those columns are identified in NHibernate mapping file and mapped to property names (in this case val and valType) based on the order in which they appear in the mapping file. The NHibernate mapping XML looks as follows. &lt;PRE class=csharpcode&gt;&amp;lt;map name=&lt;SPAN class=str&gt;"_values"&lt;/SPAN&gt; access=&lt;SPAN class=str&gt;"field"&lt;/SPAN&gt; table=&lt;SPAN class=str&gt;"Values"&lt;/SPAN&gt;&amp;gt; 
  &amp;lt;key column=&lt;SPAN class=str&gt;"ID_Parent"&lt;/SPAN&gt;&amp;gt;&amp;lt;/key&amp;gt; 
  &amp;lt;index column=&lt;SPAN class=str&gt;"Key"&lt;/SPAN&gt; type=&lt;SPAN class=str&gt;"String"&lt;/SPAN&gt;&amp;gt;&amp;lt;/&amp;lt; SPAN&amp;gt;index&amp;gt; 
  &amp;lt;element type=&lt;SPAN class=str&gt;"Samples.NHibernate.DataAccess.Object2StringUserType, 
       Samples.NHibernate.DataAccess"&lt;/SPAN&gt;&amp;gt; 
    &amp;lt;column name=&lt;SPAN class=str&gt;"Value"&lt;/SPAN&gt; /&amp;gt; 
    &amp;lt;column name=&lt;SPAN class=str&gt;"ValueType"&lt;/SPAN&gt;/&amp;gt; 
  &amp;lt;/element&amp;gt; 
&amp;lt;/map&amp;gt; &lt;/PRE&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;P&gt;Again, all of this happens behind the scenes as NHibernate is setting and fetching your objects from the database. All you know is that for any type that you put into the your dictionary, you can expect the same type to be in the dictionary for that item, even after saving and loading it from the database. 
&lt;P&gt;In conclusion, I hope that this has illustrated the flexibility that can be found within NHibernate as it relates to some more advanced mapping scenarios. If you have any questions or ideas for custom mapping types, please share!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2254247" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Microsoft+.NET+Programming/default.aspx">Microsoft .NET Programming</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/NHibernate/default.aspx">NHibernate</category></item><item><title>Designing a Domain-Driven Data Access Layer</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/04/23/designing-a-domain-driven-data-access-layer.aspx</link><pubDate>Tue, 24 Apr 2007 05:35:57 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2254244</guid><dc:creator>hdierking</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/2254244.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=2254244</wfw:commentRss><description>&lt;p&gt;(originally posted to &lt;a href="http://blogs.sarkhouston.com/hdierking/" target="_blank"&gt;Absolute Opinion&lt;/a&gt; on June 4, 2006)  &lt;p&gt;I had started writing a post about best practices for using the different NHibernate collection mapping types when it dawned on me that I may be assuming too much in thinking that we all look at data access layers in the same way. In fact, I think that it is fair to say that most folks who came through the ADO school of data access were trained to think of the data access layer as little more than a set of helper classes used to connect “business objects” to SQL Server stored procedures.  &lt;p&gt;Now, for those of you who still view the data access layer in the way that I described above, this article is not to convince you that you are wrong (even though you are). However, I think it may be fair to say that you may have trouble fitting what I’m going to describe into your way of thinking.  &lt;p&gt;So let’s start with a few very basic goals for a data access layer (DAL).  &lt;ul&gt; &lt;li&gt;The DAL should completely hide the underlying data access technology, whether it be an ORM tool like NHibernate, hand-generated inline SQL, calls to stored procedures, or anything else.  &lt;li&gt;The DAL should not place any significant constraints on the design of the domain model.  &lt;li&gt;The entire layer should be replaceable with minimal impact (or minimal risk for you PM folks).&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Now, all of the aforementioned goals can be summarized with one word: decoupling. This is a great word – it’s a word that we keep hearing over and over again with every architecture talk and every article. In fact, didn’t the introduction of component programming give us decoupling without any effort on our parts?  &lt;p&gt;In case you were wondering about that last one, the short answer is – no.  &lt;p&gt;So what should a decoupled DAL look like? In .NET programming terms, the answer lies in the references. Given our stated DAL goals, we need to be able to pull out our entire DAL and replace it with another (say one that persists our objects to and from the file system rather than a RDBMS) without causing any impact on the rest of the system. We therefore can’t have our business layer (henceforth called domain model) having any knowledge that a DAL even exists. This is due to the fact that our domain model is designed to be the very core of our system. The objects contained within the domain model form the basic language that our software system uses to describe a real world problem. Put another way, our domain model is (or, should be) a neutral layer in terms of technology concerns. The last thing that we should want to do is create a dependency on a layer whose sole focus is a technology-specific concern (persistence).  &lt;p&gt;So, getting back to observing decoupling through references, what can we deduce from my tangential diatribe above? Firstly, the DAL assembly should hold a reference to the domain model assembly – the domain model assembly should not reference the DAL in any way. Secondly, all other assemblies that need to interact with a persistent store to get and set domain objects will hold a reference to both the domain model assembly and to the DAL assembly. To pull from the SARK Classic project, such a relationship looks as follows:  &lt;p&gt;&lt;img src="http://intranet.sarkhouston.com/intranet/code/Code%20Samples/tdd_blog/LayeringArchitecture.gif" border="0"&gt;  &lt;p&gt;Now that we have an architectural view of what the DAL should look like, what should it look like at the code level? Firstly, DAL classes should be defined not in terms of “1 DAL class per 1 domain model class” but rather in terms of domain model &lt;i&gt;aggregates&lt;/i&gt;. The term aggregate was defined by Eric Evans in his book &lt;i&gt;&lt;a href="http://www.amazon.com/gp/product/0321125215/sr=8-1/qid=1149482938/ref=pd_bbs_1/002-1535884-2139211?%5Fencoding=UTF8"&gt;Domain Driven Design&lt;/a&gt;&lt;/i&gt; as follows.  &lt;p&gt;“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.”  &lt;p&gt;So you may be wondering why the terms “aggregate” and “entity” are typed in caps – well, me too – that’s just the way the book was written.  &lt;p&gt;Let’s apply that definition to the &lt;a href="http://blogs.sarkhouston.com/tdd/"&gt;SARK Classic sample project&lt;/a&gt;. A golf course has a specified number of holes – and each hole has a par value. However, the unit of change from the data perspective is always the course – i.e. – there is never a time when you would access a specific hole directly – you would always access a hole through the course. Therefore, we can say that the Course Aggregate consists of 2 classes: Course and Hole. That is the aggregate boundary. Additionally, Course is the aggregate root. In support of the aggregate boundary, DAL objects should be defined for aggregates – not specifically for domain objects.  &lt;p&gt;Once you have defined aggregate boundaries, you will hopefully find that persistence concerns can be dealt with at a more coarsely granular scope. Dealing with aggregates rather than objects may also help reduce decoupling even within the domain model. I’ve seen that many domain models have unnecessary associations between objects simply for the purpose of pulling down the entire object graph during persistence. In thinking of persistence in terms of aggregates rather than domain objects, you may also see opportunities to get rid of some of these associations and instead simply create additional query methods on the DAL object for the associated aggregate. This idea is also discussed in Eric Evans’ book, so for additional research on the topic of aggregates, it is a must.  &lt;p&gt;Now, when talking about DALs that are written in terms of a domain model rather than a technology like DataSets, critics typically raise a very good point: Why is this design technique worth losing all of the wonderful support that Visual Studio provides for RAD development? In short, it’s not. A colleague once said something very profound – it was something I was already doing, but I like the way that he said it, so I’m going to attempt to quote him. He said, “Render unto the DAL that which is the DAL’s – render unto the DataGrid that which is the DataGrid’s”. Ok, he was talking about NHibernate – and I’m generalizing a bit more – I’m certain that he will forgive me. If you’re building an ASP.NET application using a GridView, you should use the data source providers in the .NET framework to populate that GridView. Your DAL should not be concerned with dealing with tabular data (especially now that the data source providers are in the .NET Framework). Your DAL is concerned with getting and setting domain objects. See? You can have your cake and eat it too!  &lt;p&gt;Finally, let’s spend a few minutes dealing with DAL design as it relates to NHibernate. Again, I want to quickly reiterate that the DAL design style that we’ve been discussing in no way relies on NHibernate. However, there are some major benefits to using NHibernate inside of your DAL.  &lt;ul&gt; &lt;li&gt;Reflection based mapping allows complete encapsulation of object state, as it can reflect over private members.  &lt;li&gt;NHibernate keeps track of the mapped id of an object and can determine whether it is a new object (known as a transient entity) or whether it is an existing persistent object. The NHibernate API then allows you to simply call a method “SaveOrUpdate(object)” – and NHibernate will determine the type of query that needs to be run.  &lt;li&gt;NHibernate keeps track of the dirty state of object members.  &lt;li&gt;For object graphs where there are several associations, NHibernate can be optimized to use outer joining so that only one query needs to be run rather than running a query for the aggregate root’s data, then running subsequent queries for the other members of the aggregate.  &lt;li&gt;Caching anyone?  &lt;li&gt;NHibernate supports multiple RDBMSs right out of the box (or zip file)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;These are just some of the many benefits to using NHibernate as your data access technology. Over the next couple weeks we will dive into some of the specifics of using NHibernate. However, like I said at the beginning, I want to make sure that we’re all on the same page architecturally before getting into the details.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2254244" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Microsoft+.NET+Programming/default.aspx">Microsoft .NET Programming</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/NHibernate/default.aspx">NHibernate</category></item><item><title>Scrum Room?</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/04/10/scrum-room.aspx</link><pubDate>Wed, 11 Apr 2007 08:56:06 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2082271</guid><dc:creator>hdierking</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/2082271.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=2082271</wfw:commentRss><description>&lt;p&gt;If you're going to do any job, you may as well &lt;a href="http://weblogs.asp.net/bsimser/archive/2007/04/03/scrum-room-fun-room.aspx"&gt;have some fun with it&lt;/a&gt;.  Great work Bil!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2082271" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Test+Driven+Development/default.aspx">Test Driven Development</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category></item><item><title>Team System Unit Tests and Deployment Items</title><link>http://blogs.msdn.com/howard_dierking/archive/2007/02/24/team-system-unit-tests-and-deployment-items.aspx</link><pubDate>Sun, 25 Feb 2007 02:24:57 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1754599</guid><dc:creator>hdierking</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/howard_dierking/comments/1754599.aspx</comments><wfw:commentRss>http://blogs.msdn.com/howard_dierking/commentrss.aspx?PostID=1754599</wfw:commentRss><description>&lt;p&gt;Just a quick tip in case you haven't yet encountered this yet. In the course of my development rhythm, I use both &lt;a href="http://msdn2.microsoft.com/en-us/teamsystem/aa718823.aspx"&gt;Visual Studio Team Edition for Software Testers&lt;/a&gt; and &lt;a href="http://www.testdriven.net/"&gt;TestDriven.Net&lt;/a&gt; as test harnesses for my unit tests. This is primarily due to speed. As I'm sure you're aware, the VSTE test engine takes a good bit longer to initialize than TD.NET and because my programming style is very &lt;a href="http://en.wikipedia.org/wiki/Test_driven_development"&gt;TDD&lt;/a&gt; in nature, I like to run my tests more frequently, and from the test code itself. Now, I ran into a situation today where I wanted to do some testing on an Xml schema that I wrote. Therefore, I have the following test.&lt;/p&gt; &lt;div class="csharpcode"&gt;&amp;nbsp;&lt;/div&gt; &lt;div class="csharpcode"&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;[WorkItem(93), TestMethod]    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; testGetAssetTypeSchema() {    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    XmlSchema assetTypeSchema = &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;      ((IXmlSerializable) &lt;span class="kwrd"&gt;new&lt;/span&gt; AssetType(&lt;span class="str"&gt;"temp"&lt;/span&gt;)).GetSchema();    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    XmlReaderSettings xmlSettings = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlReaderSettings();    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    xmlSettings.CloseInput = &lt;span class="kwrd"&gt;true&lt;/span&gt;;    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    xmlSettings.IgnoreComments = &lt;span class="kwrd"&gt;true&lt;/span&gt;;    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    xmlSettings.IgnoreWhitespace = &lt;span class="kwrd"&gt;true&lt;/span&gt;;    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    xmlSettings.Schemas.Add(assetTypeSchema);   &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    xmlSettings.ValidationFlags = &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;      XmlSchemaValidationFlags.ProcessIdentityConstraints;   &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    xmlSettings.ValidationType = ValidationType.Schema;   &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    xmlSettings.ValidationEventHandler += &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;      &lt;span class="kwrd"&gt;new&lt;/span&gt; ValidationEventHandler(settings_ValidationEventHandler);   &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;   &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;    XmlReader xrdr = XmlReader.Create(&lt;span class="str"&gt;"Workstation.xml"&lt;/span&gt;, xmlSettings);   &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    XmlDocument xdoc = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlDocument();   &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;    xdoc.Load(xrdr);   &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;My "Workstation.xml" file sits in the project directory along with everything all of the rest of my code files. I run my test using TD.NET and I get a file IO exception – my Xml file could not be located. Oh – woops! I forgot to change the "Copy to Output Directory" property. This ensures that when I build my project, the Xml file will always get copied into the output directory along with my assemblies. To do this, I select my Xml file in the solution explorer, and look at the properties window. I can then find the "Copy to Output Directory" setting and change it to "Copy always". &lt;/p&gt;
&lt;p&gt;Now, at this point, my test will run just fine with TD.NET because that test harness runs my tests "in place". However, VSTE creates an entirely different folder structure to manage test runs and test results. Therefore, when I run my test with VSTE, my test fails again. To correct the problem, I need to add one more attribute.&lt;/p&gt;&lt;pre class="csharpcode"&gt;[WorkItem(93), DeploymentItem(&lt;span class="str"&gt;"Workstation.xml"&lt;/span&gt;), TestMethod] 
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; testGetAssetTypeSchema() { ... }&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;The "DeploymentItemAttribute" will cause the VSTE test engine to copy my Xml file from the assembly output folder to the test deployment folder – and therefore the relative path I specify in my test still works flawlessly.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1754599" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Microsoft+.NET+Programming/default.aspx">Microsoft .NET Programming</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Test+Driven+Development/default.aspx">Test Driven Development</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Visual+Studio+Team+System/default.aspx">Visual Studio Team System</category><category domain="http://blogs.msdn.com/howard_dierking/archive/tags/Agile/default.aspx">Agile</category></item></channel></rss>