<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>John Teague&#039;s Blog</title>
	<atom:link href="http://lostechies.com/johnteague/feed/" rel="self" type="application/rss+xml" />
	<link>http://lostechies.com/johnteague</link>
	<description>Just another LosTechies site</description>
	<lastBuildDate>Wed, 09 May 2012 04:56:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Austin Code Camp Schedule</title>
		<link>http://lostechies.com/johnteague/2012/05/09/austin-code-camp-schedule-2/</link>
		<comments>http://lostechies.com/johnteague/2012/05/09/austin-code-camp-schedule-2/#comments</comments>
		<pubDate>Wed, 09 May 2012 04:56:00 +0000</pubDate>
		<dc:creator>John Teague</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lostechies.com/johnteague/?p=110</guid>
		<description><![CDATA[We&#8217;ve got an amazing line up of presentations this year.  A lot of great people from the community have volunteered their time to share with the rest of what they&#8217;ve learned and what they are passionate about.  With over 40&#160;&#8230; <a href="http://lostechies.com/johnteague/2012/05/09/austin-code-camp-schedule-2/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve got an amazing line up of presentations this year.  A lot of great people from the community have volunteered their time to share with the rest of what they&#8217;ve learned and what they are passionate about.  With over 40 sessions submitted it&#8217;s going to be a great conference.</p>
<p>The list of proposed sessions are available on the web site <a href="http://austincodecamp2012.com/">http://austincodecamp2012.com</a>. Please look at the sessions and vote for the ones you find most interesting.  We use this information to place the presenations in an appropriately sized room (though some will be cancelled I&#8217;m sure)</p>
<p>It&#8217;s going to be a great conference!</p>
<p>Also if your company would like to sponsor, please contact us.</p>
<p><a href="http://www.eventbrite.com/event/3028354891?ref=ebtnebregn" target="_blank"><img src="http://www.eventbrite.com/custombutton?eid=3028354891" alt="Eventbrite - Austin Code Camp 2012" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://lostechies.com/johnteague/2012/05/09/austin-code-camp-schedule-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Austin Code Camp June 9th</title>
		<link>http://lostechies.com/johnteague/2012/04/23/austin-code-camp-june-9th/</link>
		<comments>http://lostechies.com/johnteague/2012/04/23/austin-code-camp-june-9th/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 03:46:46 +0000</pubDate>
		<dc:creator>John Teague</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lostechies.com/johnteague/?p=106</guid>
		<description><![CDATA[The 6th Austin Code Camp will be June 9th, 2012 at St Edward&#8217;s Professional Education Center.  It&#8217;s lining up to be a great conference already.  200 people have already registered and we have 30 sessions submitted too. You can find&#160;&#8230; <a href="http://lostechies.com/johnteague/2012/04/23/austin-code-camp-june-9th/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The 6th Austin Code Camp will be June 9th, 2012 at St Edward&#8217;s Professional Education Center.  It&#8217;s lining up to be a great conference already.  200 people have already registered and we have 30 sessions submitted too.</p>
<p>You can find out more at <a title="Austin Code Camp" href="http://austincodecamp2012.com">http://austincodecamp2012.com</a> You can register for the the event and also register as a speaker and submit presentations for the event.</p>
<p>All of the content in community driven, presented by members of the community.   I would encourage you to come and talk about whatever is interesting in the world of software development.  While the event is organized by the Austin .Net Users group, it is not limited to discussions about .Net.   It is an excellent opportunity to gain public speaking experience.</p>
<p>Please come join us!</p>
]]></content:encoded>
			<wfw:commentRss>http://lostechies.com/johnteague/2012/04/23/austin-code-camp-june-9th/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A year in review with CQRS</title>
		<link>http://lostechies.com/johnteague/2012/02/05/a-year-in-review-with-cqrs/</link>
		<comments>http://lostechies.com/johnteague/2012/02/05/a-year-in-review-with-cqrs/#comments</comments>
		<pubDate>Sun, 05 Feb 2012 21:31:54 +0000</pubDate>
		<dc:creator>John Teague</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lostechies.com/johnteague/?p=94</guid>
		<description><![CDATA[For the past year my team has been building and maintaining and application using CQRS with an Event Store as our persistence model.  I started gathering requirements for this project last January and the team started development in February.  We&#160;&#8230; <a href="http://lostechies.com/johnteague/2012/02/05/a-year-in-review-with-cqrs/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For the past year my team has been building and maintaining and application using CQRS with an Event Store as our persistence model.  I started gathering requirements for this project last January and the team started development in February.  We deployed the first version in June.  The first version was the bare minimum the end users needed to stop using Excel for the database and manual process.  After the initial deployment we continued to make further enhancements to put in the &#8220;Oops we really need this feature&#8221; to the application and usability enhancements to make it even more functional.  We are still working on this application today.  The business made a radical change in process and now were changing the application to meet the new needs of the business.</p>
<p>Given our history with this application and the phases we&#8217;ve gone through (initial development, maintenance / enhancements, and complete change in process) I think it&#8217;s a good case study in the feasibility of using CQRS style applications.  We&#8217;ve made some good decisions and some, err.., not so good decisions that I learned quite a bit from.</p>
<h3>A little about the Application</h3>
<p>The application is the standard &#8220;enterprise workflow&#8221; application, where the end users work product goes through several stages and different people do different tasks in order to complete the work.  These type of State-based, processes fit well with the CQRS model, as different events occur on the items in question, which determine what&#8217;s required and what action needs to take place.  There were very few &#8220;CRUD&#8221; type screens, but there were a few.</p>
<h3>My definition of CQRS</h3>
<blockquote><p>Separate models for reads and writes</p></blockquote>
<p>I think my definition heavily influenced how we built this application.  Notice there&#8217;s nothing there about messaging, MSMQ, distributed architecture, Event Sourcing, etc&#8230;  We did use some of these technologies and architecture in this app, however <em>they are not required for CQRS</em>. It&#8217;s simply an acknowledgement that the write model looks and behaves differently from the read model.  This simple acknowledgment can have profound impact on the way build your application and your ability to solve problems for your end users (and if you&#8217;re not doing that, well&#8230;)</p>
<h3>Not Everything has to fit into the CQRS Mold</h3>
<p>I think one common mistake made while building applications with CQRS is forcing every single functionality through the CQRS square hole.  There were parts of our application that were very simple and did not require the complexity of CQRS.  That&#8217;s right, CQRS is complex. I said it.  Commands must be created, validated and executed.  Events must be fired and handled.  Usually the complexity is mitigated by the simplification of the domain models.  But if you&#8217;re domain models are already simple, then a simpler approach will yield better results.</p>
<h3>Do Not Start With a Distributed Architecture</h3>
<p>When most people see examples or presentations of CQRS, it usually includes some sort of distributed architecture, where the commands and messages are put on some sort of queue, like MSMQ, RabbitMQ, or whatever.  And there can be some great advantages when using these techniques, mostly scalability.  Using a distributed approach increases the complexity to a whole new level.  However it is simply not necessary, at least at first.</p>
<p>For our application, we created a very simple in-process bus.  Meaning, execution of the command and all events were executed on the same thread.  We used an IOC container to find all of the event handlers based upon the event class type. It is a web application, so the threads were handled by the web server.  For a typical event, we had 4-6 event handlers, updating 4-5 different database tables.</p>
<p>There were some real advantages to starting with an in-process model.  We were able to get faster feedback when errors came up, and it was easier for us to find and fix bugs. This enabled us to build the application faster and get it into the end users quickly.</p>
<p>Once we were in production, we started recording metrics on the how quickly requests took and where there were performance issues.  What we discovered was the only real performance issues were when the users would perform batch operations, the same operation on many records (set based operations are nearly impossible with this architecture, or at least I haven&#8217;t figured out how to do it).  So once we determined which functions were commonly done in batch form, we moved them out of process with NServiceBus.  I think that&#8217;s one of the areas where this approach shines.  Moving these out of process, when necessary, is really simple.</p>
<blockquote><p>Move work out of process only when necessary</p></blockquote>
<h3>Think Creatively about your Domain and View Models</h3>
<p>One of the mistakes we made was the design of our domain models.  From a purely DDD / aggregate root / ubiquitous language, there was really only one AR.  But having just one AR means it&#8217;s REALLY big.  In retrospective, we should have been more creative with how we define the AR into something different.  Honestly, while this application has come complicated logic, I don&#8217;t think that we needed to solve it with a Domain Driven approach.  However, the library we used (per client request) required us to do so.  I don&#8217;t have a solution for this yet, when I do I&#8217;ll let you know (hint, I think the Actor/Model patter Chris Patterson has been talking about is a better fit).</p>
<h3>Event Sourcing &#8230; Meh</h3>
<p>Event Sourcing has been probably the most misunderstood and miscommunicated implementation strategy surrounding CQRS.  Like other pieces of the architecture, it&#8217;s an implementation choice, not a requirement for building this type of application.  Honestly, I was never sold on the concept before this project.  On this project I don&#8217;t think we got any of the benefits touted from using it.  To be clear, I think one of the problems is our implementation of the Event Sourcing persistence.  We are currently storing a binary copy of the event.  Which means that event lives in perpetuity and we can&#8217;t change it nor get rid of it. If it was serialized with something like Protocol Buffers I think we would have more flexibility, but I haven&#8217;t tested that yet so I can&#8217;t say for certain.</p>
<p>The biggest feature about using ES is the ability to replay the events and rebuild the state of your view models.  This sounds really cool, you get the ability to create new views in your application (like new reports)  and be fully avaialble with all data as if they were there from the beginning.  The only problem is that we&#8217;ve only done that once in the entire lifetime of the application.</p>
<p>But at the same time, using the event sourcing approach hasn&#8217;t really cost us anything either.  In the end, for this application, I would have been happy with just a Key-Value store of data or a document database for aggregate persistence.</p>
<p>Overall, I&#8217;m pleased with the application.  Like I said there was a big change in business process and we&#8217;ve been able to make those changes very fast in my opinion.  This is mainly due to the extreme decoupling you get from the way views are represented to how a domain object is changed or created.  I will likely continue to create applications of this type using this approach.  With a few changes underneath of course:)</p>
]]></content:encoded>
			<wfw:commentRss>http://lostechies.com/johnteague/2012/02/05/a-year-in-review-with-cqrs/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>More tickets available for Pablo&#8217;s Fiesta</title>
		<link>http://lostechies.com/johnteague/2011/09/20/more-tickets-available-for-pablos-fiesta/</link>
		<comments>http://lostechies.com/johnteague/2011/09/20/more-tickets-available-for-pablos-fiesta/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 14:07:46 +0000</pubDate>
		<dc:creator>John Teague</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lostechies.com/johnteague/?p=84</guid>
		<description><![CDATA[The conference sold out about a month ago. Since then we released tickets to everyone on the waitlist. We&#8217;ve released more tickets, so you don&#8217;t have to go on the waitlist right now. I want to make sure that everyone&#160;&#8230; <a href="http://lostechies.com/johnteague/2011/09/20/more-tickets-available-for-pablos-fiesta/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The conference sold out about a month ago.  Since then we released tickets to everyone on the waitlist.  We&#8217;ve released more tickets, so you don&#8217;t have to go on the waitlist right now.  I want to make sure that everyone who does want to attend can, so I&#8217;ll try to keep the tickets available up until the cutoff date, which is Sept. 28.  So if these tickets sell out, be sure and sign up on the waitlist.</p>
<p><a href="http://bit.ly/ieUPl1">http://bit.ly/ieUPl1</a></p>
]]></content:encoded>
			<wfw:commentRss>http://lostechies.com/johnteague/2011/09/20/more-tickets-available-for-pablos-fiesta/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Austin Code Camp Sessions</title>
		<link>http://lostechies.com/johnteague/2011/08/09/austin-code-camp-sessions/</link>
		<comments>http://lostechies.com/johnteague/2011/08/09/austin-code-camp-sessions/#comments</comments>
		<pubDate>Tue, 09 Aug 2011 17:54:33 +0000</pubDate>
		<dc:creator>John Teague</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lostechies.com/johnteague/?p=82</guid>
		<description><![CDATA[The list of Austin Code Camp sessions are up. (Except for mine, I submitted late sorry) http://bit.ly/qHQq48 If you haven&#8217;t registered for CodeCamp, go here http://bit.ly/jrQ1Qs As always it&#8217;s free.]]></description>
			<content:encoded><![CDATA[<p>The list of Austin Code Camp sessions are up. (Except for mine, I submitted late sorry)</p>
<p>http://bit.ly/qHQq48</p>
<p>If you haven&#8217;t registered for CodeCamp, go here http://bit.ly/jrQ1Qs</p>
<p>As always it&#8217;s free.</p>
]]></content:encoded>
			<wfw:commentRss>http://lostechies.com/johnteague/2011/08/09/austin-code-camp-sessions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>It&#8217;s All About the Conversation</title>
		<link>http://lostechies.com/johnteague/2011/06/24/its-all-about-the-conversation/</link>
		<comments>http://lostechies.com/johnteague/2011/06/24/its-all-about-the-conversation/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 18:49:47 +0000</pubDate>
		<dc:creator>John Teague</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lostechies.com/johnteague/?p=74</guid>
		<description><![CDATA[Join us at Los Techies Fiesta Open Space Conference September 30, October 1, &#38; 2. An Open Space conference is really a different experience than the traditional, presentation driven conference.  While both formats are about learning new things, they go&#160;&#8230; <a href="http://lostechies.com/johnteague/2011/06/24/its-all-about-the-conversation/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Join us at <a title="Pablo's Fiesta" href="bit.ly/pablosfiesta" target="_blank">Los Techies Fiesta Open Space Conference</a> September 30, October 1, &amp; 2.</p>
<p>An Open Space conference is really a different experience than the traditional, presentation driven conference.  While both formats are about learning new things, they go about it in entirely different ways.  An Open Space conference is more about the conversation than anything.  The way I often describe it is if you&#8217;ve ever gone to a conference and the most stimulating moment was a conversation in the hallway or break room, that&#8217;s an Open Space conference all day long.</p>
<blockquote><p>If you&#8217;ve ever gone to a conference and the most stimulating moment was a conversation in the hallway or break room, that&#8217;s an Open Space conference all day long.</p></blockquote>
<p>The environment is very fluid and active.  This is due to the <a title="Law of Two Feet" href="http://en.wikipedia.org/wiki/Open_Space_Technology#Law_of_Two_Feet" target="_blank">Law of Two Feet</a> and  the schedule is determined by the attendees.  Unlike a presentation focused event, where you tend to sit still and listen to someone for an hour or more, you are actively encouraged to move around and keep engaged.  If a session isn&#8217;t going the way you want, just go to another, or start your own.</p>
<p>The self-organizing aspect of the format is really important.  Even though I am one of the organizers of the event, I have almost no say in  what the topics and sessions are about (I&#8217;ll be proposing topics and help organize the proposals, so I have a little say).  And the fact that speakers don&#8217;t submit their sessions months in advance, the topics are usually very current and relevant.</p>
<p>At last year&#8217;s Los Techies Fiesta, a couple of the sessions really stood out for me.  One of the sessions I proposed was on NoSQL options.  At that time I had never used any of the NoSql tools and knew very little about them, but it was a topic that I wanted to learn more about.  It was an amazing session.  I learned about Mongodb, Cassandra, Redis, and several others.  I learned the difference between document databases, Key Value storage and Column Oriented databases.  Even though I was the &#8220;facilitator&#8221;, I  knew very little about the topic, everyone their shared their experiences and knowledge for a highly enlightening conversation.</p>
<p>I hope you&#8217;ll join us this year and share your knowledge with us!</p>
<p><a href="http://fiesta2011.eventbrite.com?ref=ebtn" target="_blank"><img src="http://www.eventbrite.com/registerbutton?eid=1023708941" border="0" alt="Register for Los Techies Fiesta  2011 in Austin, TX  on Eventbrite" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://lostechies.com/johnteague/2011/06/24/its-all-about-the-conversation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Convention Based Filters</title>
		<link>http://lostechies.com/johnteague/2011/06/12/convention-based-filters/</link>
		<comments>http://lostechies.com/johnteague/2011/06/12/convention-based-filters/#comments</comments>
		<pubDate>Sun, 12 Jun 2011 21:43:16 +0000</pubDate>
		<dc:creator>John Teague</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lostechies.com/johnteague/?p=63</guid>
		<description><![CDATA[Title: Convention Based Filters Not too long ago Joshua Flanagan spoke at the Austin .Net User Group about how the Dovetail crew use conventions to simplify their development process. The approach is simple in concept (of course the devil’s in&#160;&#8230; <a href="http://lostechies.com/johnteague/2011/06/12/convention-based-filters/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Title: Convention Based Filters</p>
<p>Not too long ago <a href="http://joshflanagan.lostechies.com">Joshua Flanagan</a> spoke at the <a href="http://adnug.org">Austin .Net User Group</a> about how the Dovetail crew use conventions to simplify their development process.  The approach is simple in concept (of course the devil’s in the details)</p>
<p>This inspired me to apply the approach in my current project.  Our project has several screens that very similar: a table, some buttons to perform actions, and a set of filters.  When we implemented the first screen, it was obvious that building the filters were going to get old really fast.  This looked like a good place to try and make things a little easier.</p>
<p>I started by creating a class for the fields that were on a filter and used the properties in the class to create an NHibernate Criteria search.  The only real requirement here is that the property names in the filter class had to match the names in the Nhiberante mapped object.</p>
<p>This was pretty easy to setup.  All we needed to do was build up the Criteria from the property names and the values.</p>
<pre>public IEnumerable&lt;ICriterion&gt; CreateFilter(object filter, Type objectToFilter)
{
  var criterion = new List&lt;ICriterion&gt;();
  var props = filter.GetType().GetProperties();
  foreach (var pi in props)
  {
    var val = pi.GetValue(filter, null);
    if (ShouldNotAddToFilter(pi, val)) continue;
    criterion.Add(new SimpleExpression(pi.Name, val, "="));
    return criterion;
}</pre>
<p>Now this will create a very simple criteria by creating where statement with a bunch of Property = value OR Property2 = value2.  While this is functional and does cover most of our needs, it is pretty limited in what it could do.  One issue is that it only goes one level deep in your persistence model hiearchy.  You would not be able to apply filters to anything modeled as components.  Also there were a few fields that needed to be queried using expressions other than equals.  We needed to do like filters as well as greater than / less than queries too.  So we need to provide some metadata for the properties to make variations on the criteria output.  The easiest way to do that is to decorate the filter properties with some attributes.</p>
<p>We created a set of Attribute classes that allowed us to create different types of Criteria Expressions.  The type of expression needed was created inside the attribute.  We can then use the power of polymorphism to avoid a big <a href="http://www.antiifcampaign.com/">if or switch</a> statement and keeps the query building code clean.</p>
<pre>public class QueryFilterAttribute : Attribute
{
  public virtual ICriterion GetCriteria(string propertyName, object val)
  {
    return Restrictions.Eq(propertyName, val);
  }
  public Type ComponentModel { get; set; }
}</pre>
<pre>public class LikeQueryFilterAttribute : QueryFilterAttribute
{
  public override ICriterion GetCriteria(string propertyName, object val)
  {
    return new LikeExpression(propertyName, val.ToString(), MatchMode.Anywhere);
  }
}</pre>
<p>These attributes allow us to change the Criteria Expression or Apply the filter to a Component Type. The full source code is at the <a href="https://gist.github.com/1007612">gist</a> below.</p>
<p>This relatively simple construct saved us a lot time, especially when you think about how much code we would have written after about 10 or 12 of these by hand.  When you start to put these types of conventions in your entire codebase, they add up to a lot of time savings.  Just another example of how working smarter, not harder can make your life a little bit easier.</p>
<pre><code><div id="gist-1007612" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">class</span> <span class="nc">BasicFilter</span> </div><div class='line' id='LC2'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="n">Guid</span><span class="p">?</span> <span class="n">ClientGroupId</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="na">            [LikeQueryFilter(ComponentModel = typeof (Address))]</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="kt">string</span> <span class="n">AddressCity</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="na">            [QueryFilter(ComponentModel = typeof (Address))]</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="kt">string</span> <span class="n">AddressState</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><span class="na">            [QueryFilter(ComponentModel = typeof (Address))]</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="kt">string</span> <span class="n">AddressZip</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC13'><br/></div><div class='line' id='LC14'><span class="na">            [LikeQueryFilter(ComponentModel = typeof (Address))]</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="kt">string</span> <span class="n">AddressLine1</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'><span class="na">            [LikeQueryFilter(ComponentModel = typeof (Address))]</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="kt">string</span> <span class="n">AddressLine2</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC19'><br/></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="kt">int?</span> <span class="n">ClientId</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC21'><br/></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="kt">long?</span> <span class="n">PropertyId</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="n">Guid</span> <span class="n">AssignedToUserId</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1007612/194acb68c9793949cd62ebebc032983338e5df6e/BasicFilter.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1007612#file_basic_filter.cs" style="float:right;margin-right:10px;color:#666">BasicFilter.cs</a>
            <a href="https://gist.github.com/1007612">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><br/></div><div class='line' id='LC2'><span class="k">public</span> <span class="k">class</span> <span class="nc">FilterQueryBuilder</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="n">IEnumerable</span><span class="p">&lt;</span><span class="n">ICriterion</span><span class="p">&gt;</span> <span class="n">CreateFilter</span><span class="p">(</span><span class="kt">object</span> <span class="n">filter</span><span class="p">,</span> <span class="n">Type</span> <span class="n">objectToFilter</span><span class="p">)</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">var</span> <span class="n">criterion</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">ICriterion</span><span class="p">&gt;();</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">var</span> <span class="n">props</span> <span class="p">=</span> <span class="n">filter</span><span class="p">.</span><span class="n">GetType</span><span class="p">().</span><span class="n">GetProperties</span><span class="p">();</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">pi</span> <span class="k">in</span> <span class="n">props</span><span class="p">)</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">var</span> <span class="n">val</span> <span class="p">=</span> <span class="n">pi</span><span class="p">.</span><span class="n">GetValue</span><span class="p">(</span><span class="n">filter</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="n">ShouldNotAddToFilter</span><span class="p">(</span><span class="n">pi</span><span class="p">,</span> <span class="n">val</span><span class="p">))</span> <span class="k">continue</span><span class="p">;</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">var</span> <span class="n">queryAttribute</span> <span class="p">=</span> <span class="p">(</span><span class="n">QueryFilterAttribute</span><span class="p">)</span> <span class="n">pi</span><span class="p">.</span><span class="n">GetCustomAttributes</span><span class="p">(</span><span class="k">typeof</span> <span class="p">(</span><span class="n">QueryFilterAttribute</span><span class="p">),</span> <span class="k">true</span><span class="p">).</span><span class="n">FirstOrDefault</span><span class="p">();</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="n">queryAttribute</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">criterion</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="k">new</span> <span class="n">SimpleExpression</span><span class="p">(</span><span class="n">pi</span><span class="p">.</span><span class="n">Name</span><span class="p">,</span> <span class="n">val</span><span class="p">,</span> <span class="s">&quot;=&quot;</span><span class="p">));</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">continue</span><span class="p">;</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">var</span> <span class="n">name_to_return</span> <span class="p">=</span> <span class="n">GetNameFromAttribute</span><span class="p">(</span><span class="n">queryAttribute</span><span class="p">,</span> <span class="n">pi</span><span class="p">,</span> <span class="n">objectToFilter</span><span class="p">);</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">criterion</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">queryAttribute</span><span class="p">.</span><span class="n">GetCriteria</span><span class="p">(</span><span class="n">name_to_return</span><span class="p">,</span> <span class="n">val</span><span class="p">));</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">criterion</span><span class="p">;</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC23'><br/></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">static</span> <span class="kt">bool</span> <span class="nf">ShouldNotAddToFilter</span><span class="p">(</span><span class="n">PropertyInfo</span> <span class="n">pi</span><span class="p">,</span> <span class="kt">object</span> <span class="n">propertyValue</span><span class="p">)</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="n">propertyValue</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span> <span class="k">return</span> <span class="k">true</span><span class="p">;</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span><span class="p">(</span><span class="n">pi</span><span class="p">.</span><span class="n">GetCustomAttributes</span><span class="p">(</span><span class="k">false</span><span class="p">).</span><span class="n">Any</span><span class="p">(</span><span class="n">x</span><span class="p">=&gt;</span><span class="n">x</span> <span class="k">is</span> <span class="n">NotAFilter</span><span class="p">))</span> <span class="k">return</span> <span class="k">true</span><span class="p">;</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">pi</span><span class="p">.</span><span class="n">PropertyType</span> <span class="p">==</span> <span class="k">typeof</span> <span class="p">(</span><span class="n">Guid</span><span class="p">)</span> <span class="p">&amp;&amp;</span> <span class="p">(</span><span class="n">Guid</span><span class="p">)</span> <span class="n">propertyValue</span> <span class="p">==</span> <span class="n">Guid</span><span class="p">.</span><span class="n">Empty</span><span class="p">;</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC30'><br/></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">static</span> <span class="kt">string</span> <span class="nf">GetNameFromAttribute</span><span class="p">(</span><span class="n">QueryFilterAttribute</span> <span class="n">queryAttribute</span><span class="p">,</span> <span class="n">PropertyInfo</span> <span class="n">filterProperty</span><span class="p">,</span> <span class="n">Type</span> <span class="n">objectToFilter</span><span class="p">)</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="n">queryAttribute</span><span class="p">.</span><span class="n">ComponentModel</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span> <span class="k">return</span> <span class="n">filterProperty</span><span class="p">.</span><span class="n">Name</span><span class="p">;</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">var</span> <span class="n">filter_property_name</span> <span class="p">=</span> <span class="n">filterProperty</span><span class="p">.</span><span class="n">Name</span><span class="p">;</span></div><div class='line' id='LC35'><br/></div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">var</span> <span class="n">filtered_type_property_name</span> <span class="p">=</span> <span class="n">objectToFilter</span><span class="p">.</span><span class="n">GetProperties</span><span class="p">()</span></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">info</span> <span class="p">=&gt;</span> <span class="n">info</span><span class="p">.</span><span class="n">PropertyType</span> <span class="p">==</span> <span class="n">queryAttribute</span><span class="p">.</span><span class="n">ComponentModel</span> <span class="p">&amp;&amp;</span> <span class="n">filter_property_name</span><span class="p">.</span><span class="n">StartsWith</span><span class="p">(</span><span class="n">info</span><span class="p">.</span><span class="n">Name</span><span class="p">)).</span><span class="n">First</span><span class="p">().</span><span class="n">Name</span><span class="p">;</span></div><div class='line' id='LC38'><br/></div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">var</span> <span class="n">component_property_name</span> <span class="p">=</span> <span class="n">filterProperty</span><span class="p">.</span><span class="n">Name</span><span class="p">.</span><span class="n">Replace</span><span class="p">(</span><span class="n">filtered_type_property_name</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">);</span></div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">filtered_type_property_name</span> <span class="p">+</span> <span class="s">&quot;.&quot;</span> <span class="p">+</span> <span class="n">component_property_name</span><span class="p">;</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1007612/7c32ca0c5bc557b9b452161c010535997d48f0a0/FilterQueryBuilder.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1007612#file_filter_query_builder.cs" style="float:right;margin-right:10px;color:#666">FilterQueryBuilder.cs</a>
            <a href="https://gist.github.com/1007612">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">class</span> <span class="nc">NotAFilter</span><span class="p">:</span> <span class="n">Attribute</span></div><div class='line' id='LC2'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">class</span> <span class="nc">FilterGroup</span> <span class="p">:</span> <span class="n">Attribute</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="nf">FilterGroup</span><span class="p">(</span><span class="kt">string</span> <span class="n">displayName</span><span class="p">)</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">DisplayName</span> <span class="p">=</span> <span class="n">displayName</span><span class="p">;</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="nf">FilterGroup</span><span class="p">()</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="kt">string</span> <span class="n">DisplayName</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC19'><br/></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">class</span> <span class="nc">QueryFilterAttribute</span> <span class="p">:</span> <span class="n">Attribute</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">virtual</span> <span class="n">ICriterion</span> <span class="nf">GetCriteria</span><span class="p">(</span><span class="kt">string</span> <span class="n">propertyName</span><span class="p">,</span> <span class="kt">object</span> <span class="n">val</span><span class="p">)</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">Restrictions</span><span class="p">.</span><span class="n">Eq</span><span class="p">(</span><span class="n">propertyName</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="n">Type</span> <span class="n">ComponentModel</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC28'><br/></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">class</span> <span class="nc">LikeQueryFilterAttribute</span> <span class="p">:</span> <span class="n">QueryFilterAttribute</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">override</span> <span class="n">ICriterion</span> <span class="nf">GetCriteria</span><span class="p">(</span><span class="kt">string</span> <span class="n">propertyName</span><span class="p">,</span> <span class="kt">object</span> <span class="n">val</span><span class="p">)</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="k">new</span> <span class="nf">LikeExpression</span><span class="p">(</span><span class="n">propertyName</span><span class="p">,</span> <span class="n">val</span><span class="p">.</span><span class="n">ToString</span><span class="p">(),</span> <span class="n">MatchMode</span><span class="p">.</span><span class="n">Anywhere</span><span class="p">);</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC36'><br/></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">class</span> <span class="nc">DayPrecisionDateQueryFilterAttribute</span> <span class="p">:</span> <span class="n">QueryFilterAttribute</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">override</span> <span class="n">ICriterion</span> <span class="nf">GetCriteria</span><span class="p">(</span><span class="kt">string</span> <span class="n">propertyName</span><span class="p">,</span> <span class="kt">object</span> <span class="n">val</span><span class="p">)</span></div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">var</span> <span class="k">value</span> <span class="p">=</span> <span class="p">(</span><span class="n">DateTimeOffset</span><span class="p">)</span> <span class="n">val</span><span class="p">;</span></div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="k">new</span> <span class="nf">BetweenExpression</span><span class="p">(</span><span class="n">propertyName</span><span class="p">,</span> <span class="k">value</span><span class="p">,</span> <span class="k">value</span><span class="p">.</span><span class="n">AddDays</span><span class="p">(</span><span class="m">1</span><span class="p">).</span><span class="n">AddMilliseconds</span><span class="p">(-</span><span class="m">1</span><span class="p">));</span></div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC45'><br/></div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">class</span> <span class="nc">IgnoreFilterAttribute</span> <span class="p">:</span> <span class="n">QueryFilterAttribute</span></div><div class='line' id='LC47'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC48'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">override</span> <span class="n">ICriterion</span> <span class="nf">GetCriteria</span><span class="p">(</span><span class="kt">string</span> <span class="n">propertyName</span><span class="p">,</span> <span class="kt">object</span> <span class="n">val</span><span class="p">)</span></div><div class='line' id='LC49'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC50'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="k">new</span> <span class="nf">NotNullExpression</span><span class="p">(</span><span class="n">propertyName</span><span class="p">);</span></div><div class='line' id='LC51'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC52'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC53'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC54'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">class</span> <span class="nc">GreaterThanFilterAttribute</span> <span class="p">:</span> <span class="n">QueryFilterAttribute</span></div><div class='line' id='LC55'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC56'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">override</span> <span class="n">ICriterion</span> <span class="nf">GetCriteria</span><span class="p">(</span><span class="kt">string</span> <span class="n">propertyName</span><span class="p">,</span> <span class="kt">object</span> <span class="n">val</span><span class="p">)</span></div><div class='line' id='LC57'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC58'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">Restrictions</span><span class="p">.</span><span class="n">Gt</span><span class="p">(</span><span class="n">propertyName</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span></div><div class='line' id='LC59'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC60'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1007612/55f028f6fd9a144da5317329122278b79c0ee20e/QueryFilterAttributes.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1007612#file_query_filter_attributes.cs" style="float:right;margin-right:10px;color:#666">QueryFilterAttributes.cs</a>
            <a href="https://gist.github.com/1007612">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</code></pre>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://lostechies.com/johnteague/2011/06/12/convention-based-filters/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Bootstrapping Your Application From IronRuby</title>
		<link>http://lostechies.com/johnteague/2011/04/07/bootstrapping-your-application-from-ironruby/</link>
		<comments>http://lostechies.com/johnteague/2011/04/07/bootstrapping-your-application-from-ironruby/#comments</comments>
		<pubDate>Thu, 07 Apr 2011 17:55:51 +0000</pubDate>
		<dc:creator>John Teague</dc:creator>
				<category><![CDATA[iron ruby]]></category>
		<category><![CDATA[Iron Ruby]]></category>

		<guid isPermaLink="false">http://lostechies.com/johnteague/2011/04/07/bootstrapping-your-application-from-ironruby/</guid>
		<description><![CDATA[I think one of the best use cases for IronRuby is to use it as an automation tool and scripting platform for your domain application. The first hurdle I had to make this possible was Bootstrapping the application so that&#160;&#8230; <a href="http://lostechies.com/johnteague/2011/04/07/bootstrapping-your-application-from-ironruby/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p class="brush:ruby">I think one of the best use cases for IronRuby is to use it as an automation tool and scripting platform for your domain application. The first hurdle I had to make this possible was Bootstrapping the application so that it can run from the IronRuby runtime. Among other things we need to initialize StructureMap and AutoMapper. Because you&#8217;re executing the IR.exe in it&#8217;s own AppDomain, there a couple of thing you have to do first.</p>
<p class="brush:ruby">Using StructureMap from IronRuby StructureMap can be loaded and accessed from IR without difficulty. But I find the syntax to use generic methods in IronRuby a bit noisy. So I made a simple module that wraps the StructureMap generic methods. We see these used in a minute.</p>
<pre>require 'StructureMap'
include StructureMap
#module to hide the IronRuby generic noise
module ObjectFactoryModule
    def get_instance type_name
        ObjectFactory.method(:get_instance).of(type_name).call
    end
    def inject(type,instance)
        ObjectFactory.method(:inject).of(type).call(instance)
    end
    def eject(type)
        ObjectFactory.method(:eject_all_instances_of).of(type).call
    end

    def replace(type,instance)
        ObjectFactory.method(:eject_all_instances_of).of(type).call
        ObjectFactory.method(:inject).of(type).call(instance)
    end
end</pre>
<p>&nbsp;</p>
<h2>Config files are your enemy</h2>
<p>Because IronRuby runs in its own AppDomain, it is impossible to directly access your config files from IR without some serious <a href="http://vaderpi.com/blog/?p=609">hackery</a>.  But this it is not impossible to get around this if you encapsulate application settings behind an interface, with the default implementation getting values from configuration files.  We have a very simple interface:</p>
<p>You can create a ruby class that implements the IApplicationSettings interface by including the interface.</p>
<p>&nbsp;</p>
<pre>require 'PropertyRegistration.Common'
include PropertyRegistration::Common
include ObjectFactoryModule
class ScriptingApplicationSettings
    include IApplicationSettings

    def EventSourceDBConnectionString
        return 'Data Source=localhost;Initial Catalog=db;Integrated Security=SSPI'
    end
    def ViewModelConnectionString
        return 'Data Source=localhost;Initial Catalog=db;Integrated Security=SSPI'
    end
    def FasTrackDbConnectionString
        return 'Data Source=localhost;Initial Catalog=db;Integrated Security=SSPI'
    end
    def CurrentSessionContextClass
        return 'thread_static'
    end
    def ViewModelDefaultSchema
        return '[PropertyRegistration_ViewSource].[dbo]'
    end
    def LoadZipcodeDatabaseData
        return false
    end
end</pre>
<p>&nbsp;</p>
<p>Now here&#8217;s the cool part we can inject the ruby class into structuremap so that it will be the implementation of IApplicationSettings.</p>
<pre>$LOAD_PATH &lt;&lt; File.dirname(__FILE__) + "/assemblies"
require 'Rake'
dlls = FileList.new(File.join(File.dirname(__FILE__),"assemblies/*.dll"))
dlls.each {|f|require f}
require 'StructureMap'
require 'ObjectFactoryModule.rb'
require 'ApplicationSettings.rb'
require 'PropertyRegistration.DataLoader'

include ObjectFactoryModule
include PropertyRegistration::DataLoader::Application
include StructureMap

#bootstrapper, loading StructureMap registries and other stuff
BootStrapper.startup

settings = ScriptingApplicationSettings.new
# ejecting IApplicationSettings and replacing with ruby class
replace PropertyRegistration::Common::IApplicationSettings, settings</pre>
<p>&nbsp;</p>
<p>Now, we have loaded all of our assemblies, Called our bootstrapper to initialize StructureMap and everything else.  Then we replaced the default implementation of IApplicationSettings with our Ruby implementation and our application is none the wiser.  We can now use the IApplicationSettings from StructureMap as well as any classes that have it as a dependency.</p>
<p>exporter = get_instance(DataLoader::SchemaExporter)<br />
exporter.generate_schema</p>
<p>There was more work involved getting everything to run from Rake, but this is the basic wiring and the other stuff is not really important.</p>
<p>I have bigger plans for using IronRuby with my applications.  This was the first step.  I&#8217;ll post more as my journey continues.</p>
]]></content:encoded>
			<wfw:commentRss>http://lostechies.com/johnteague/2011/04/07/bootstrapping-your-application-from-ironruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Less Is More</title>
		<link>http://lostechies.com/johnteague/2011/03/03/less-is-more/</link>
		<comments>http://lostechies.com/johnteague/2011/03/03/less-is-more/#comments</comments>
		<pubDate>Thu, 03 Mar 2011 05:16:00 +0000</pubDate>
		<dc:creator>John Teague</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">/blogs/johnteague/archive/2011/03/03/less-is-more.aspx</guid>
		<description><![CDATA[I started a new project this year and part of my responsibilities is gathering requirements and converting them to user stories and acceptance criteria. &#160;It&#8217;s been a very interesting experience for me and put me a little out of my&#160;&#8230; <a href="http://lostechies.com/johnteague/2011/03/03/less-is-more/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><p>I started a new project this year and part of my responsibilities is gathering requirements and converting them to user stories and acceptance criteria. &nbsp;It&#8217;s been a very interesting experience for me and put me a little out of my comfort zone. &nbsp;I&#8217;ve been sheltered most of my career, with someone else there to drive out these requirements. &nbsp;It&#8217;s actually taught or reinforced a lot of things that I think are very important.</p>
<h3>Distilling to Minimum Viable Product</h3>
<p>Before this project I was sharing office space at a startup incubator, where people with an idea were given some direction and focused on what they really need to do first as a startup: get customers. &nbsp;One term I heard over and over was Minimum Viable Product. &nbsp;What is the smallest thing of value you can launch with? &nbsp;I&#8217;m taking the same approach with an enterprise application: what&#8217;s the smallest set of features you need to stop using you&#8217;re homegrown excel application. &nbsp;The interesting thing to me is that I&#8217;m not just reminding the business owner, but also myself.</p>
<h3>Do the simplest thing that works until it doesn&#8217;t</h3>
<p>What&#8217;s the simplest thing you can do to solve the problem but also follows sound software design principles? I&#8217;m not saying you should cut corners on your architecture to complete the application quickly, in fact the opposite. &nbsp;No matter how well you can elicit requirements from business owners and no matter how many thought provoking questions you ask, until users start using the application, the users simply won&#8217;t know everything they need until they start using the application. &nbsp;By using a modular design that&#8217;s has easy to replace functionality you can keep the process simple and change it when you have better information</p>
<h3>YAGNI</h3>
<p>You Ain&#8217;t Gonna Need It. &nbsp;It&#8217;s one of my favorite acronyms, but it&#8217;s harder to adhere to than you might think. &nbsp;When you&#8217;re gathering requirements you often hear about things the business owners want to do in the future. &nbsp;Plus it&#8217;s just in our nature to build in everything we can. &nbsp;It takes a great deal of restraint to build an application that is useful in 3 months instead of the perfect solution in 8.</p>
<h3>The 80 / 20 Rule</h3>
<p>This is probably the most difficult thing for programmers to remember: not everything has to be solved in the application. &nbsp;Today we we&#8217;re hashing out the stories dealing with escalation. &nbsp;There were one or two scenarios where the person handling escalation couldn&#8217;t solve the problem themselves, but needed either a manager or some other team member to do something. &nbsp;There&#8217;s no doubt this could be done within the application, but the reality was that it would just be faster if they asked the person either in person or on the phone or in an email to make the change for them. &nbsp;Since it was only one or two cases out of 15 or 20, it didn&#8217;t make sense to have this part of the minimum viable product. &nbsp;</p>
<p>It&#8217;s possible that our analysis is wrong and it happens way more often than we think. &nbsp;But at this point we don&#8217;t know and trying to build it now would add weeks to initial deployment. &nbsp;There are plenty of cases where it&#8217;s just better to handle edge cases outside of the application. &nbsp;The important part is to gather data so that you can either confirm or refute your original hypothesis</p>
<h3>Metrics</h3>
<p>A lot of assumptions are made during the initial development of an application. &nbsp;You need to be able to validate those assumptions and one way to do that is to gather as much data about usage as you can. &nbsp;From click throughs to thorough logging, capturing usage data is crucial to find the holes in your initial assumptions.</p>
<p>We&#8217;re one of the few professions where it&#8217;s okay to build something with imperfect information. &nbsp;We have the ability to improve our designs after people start using it. &nbsp;It&#8217;s okay to get a few things wrong as long as you design your system so that you can make changes quickly. &nbsp;Low coupling, design by contract, and high test coverage help you do that. &nbsp; By applying restraint in our design and architecture and incrementally improving applications can lead to really great software</p></p>
]]></content:encoded>
			<wfw:commentRss>http://lostechies.com/johnteague/2011/03/03/less-is-more/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using a Command Execution Style Architecture with a Domain Model</title>
		<link>http://lostechies.com/johnteague/2010/11/23/using-a-command-execution-style-architecture-with-a-domain-model/</link>
		<comments>http://lostechies.com/johnteague/2010/11/23/using-a-command-execution-style-architecture-with-a-domain-model/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 04:17:03 +0000</pubDate>
		<dc:creator>John Teague</dc:creator>
				<category><![CDATA[Command Processor Pattern]]></category>
		<category><![CDATA[DDD]]></category>

		<guid isPermaLink="false">/blogs/johnteague/archive/2010/11/22/using-a-command-execution-style-architecture-with-a-domain-model.aspx</guid>
		<description><![CDATA[Kyle Baley has an interesting article about how he’s using commands to break up the logic of his application into small manageable pieces. I’m using the same command processor pattern for a project I’ve working on as well.&#160; It&#8217;s a&#160;&#8230; <a href="http://lostechies.com/johnteague/2010/11/23/using-a-command-execution-style-architecture-with-a-domain-model/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Kyle Baley has an interesting <a href="http://codebetter.com/blogs/kyle.baley/archive/2010/10/20/command-pattern-architecture-or-how-to-do-it-a-little-at-a-time.aspx">article</a> about how he’s using commands to break up the logic of his application into small manageable pieces. I’m using the same command processor pattern for a project I’ve working on as well.&#160; It&#8217;s a great way for breaking up those &quot;service&quot; classes that really just end up as great big lint collectors for various methods.</p>
<p>Kyle mentions that in his application, he still has a very anemic domain model and most of the work happens when a command is processed. However, it&#8217;s entirely possible to use a full domain model with the commands, and really make things easier in the long run.&#160; The commands do the same job the service methods did: collect information necessary for the domain models to do their job.&#160; Once that&#8217;s done, the info should be passed to your domain model to determine what to do with it. </p>
<p>There are two reasons (that I can think of) why I think anemic domain models will cause problems in command based architectures.&#160; First, just as with service layer architecture, if you&#8217;re service layer is making decisions about what state your domain objects should be in, then the only way you can change the state of your domain object is by processing a command.&#160; Another problem is that, while using commands, makes it easier to understand what each command is doing, it also hides the process somewhat.&#160; When a command executor is responsible for finding the correct command to execute, it can be more difficult to manually fire off the correct command to execute.&#160; If there is important logic hidden in the command, it is more likely to be duplicated rather than referred.</p>
<p>Regardless of whether you use a Service Layer or a Command Processor architecture, the important part is to keep all of the logic that keeps your domain objects in a valid state within the domain object.&#160; This will promote the reuse of logic, increase the cohesion of you domain objects, and reduce the coupling to other components to maintain proper state of an object through it’s lifetime.</p>
]]></content:encoded>
			<wfw:commentRss>http://lostechies.com/johnteague/2010/11/23/using-a-command-execution-style-architecture-with-a-domain-model/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>

