<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Rob's Blog</title>
        <link>http://robrich.org/Default.aspx</link>
        <description>Rob's Blog</description>
        <language>en-US</language>
        <copyright>Rob Richardson</copyright>
        <generator>Subtext Version 2.5.0.3</generator>
        <image>
            <title>Rob's Blog</title>
            <url>http://robrich.org/images/RSS2Image.gif</url>
            <link>http://robrich.org/Default.aspx</link>
            <width>77</width>
            <height>60</height>
        </image>
        <item>
            <title>Elmah: return the ErrorId from Signal.Raise()</title>
            <category>Code</category>
            <category>Rants</category>
            <link>http://robrich.org/archive/2012/05/02/Elmah-return-the-ErrorId-from-Signal-Raise.aspx</link>
            <description>&lt;a href="http://code.google.com/p/elmah"&gt;ELMAH&lt;/a&gt; is an awesome error logging framework for ASP.NET.  It provides both an elegant way of capturing errors, and an elegant way of displaying them later.  It's available as a NuGet package, and is both Web Forms and MVC friendly.&lt;br /&gt;
&lt;br /&gt;
Generally, Elmah "just works" and you can walk away happy as a clam.  But there's &lt;a href="http://stackoverflow.com/questions/766610/how-to-get-elmah-to-work-with-asp-net-mvc-handleerror-attribute/779961#779961"&gt;times&lt;/a&gt; where you want to do custom error logging.  The general solution is to do something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;ErrorSignal.FromContext(HttpContext.Current).Raise(ex, HttpContext.Current);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The up-side is you can log anything you want then gently recover.  The down-side is you can't get the logged ErrorId.  Granted, based on your Elmah filters, maybe it wasn't logged.  But if it was and that location stores an id (see Elmah's SqlErrorLog) then it'd be really nice for &lt;span style="font-family: Courier New;"&gt;Raise()&lt;/span&gt; to return that Id.&lt;br /&gt;
&lt;br /&gt;
The problem is elegantly described &lt;a href="http://code.google.com/p/elmah/issues/detail?id=148"&gt;http://code.google.com/p/elmah/issues/detail?id=148&lt;/a&gt; and &lt;a href="http://stackoverflow.com/questions/7895271/getting-the-id-of-an-error-in-elmah-after-calling-raise/7902138"&gt;http://stackoverflow.com/questions/7895271/getting-the-id-of-an-error-in-elmah-after-calling-raise/7902138&lt;/a&gt; with nearly identical results: "You can't get there from here, don't bother."&lt;br /&gt;
&lt;br /&gt;
The closest work-around is to listen to the ErrorLogModule's Logged event, and shim it to where you need it:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;void ErrorLog_Logged(object sender, ErrorLoggedEventArgs args) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         string key = args.Entry.Id;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         // stash this somewhere&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Then after the .Raise() call, you pull it from the stash location.  HttpRequest.Items is request-specific cache, and provides a descent stash location.  But this is at best a fragile hack.&lt;br /&gt;
&lt;br /&gt;
As any good programmer would say, this is a problem that can easily be solved with code.  I downloaded the Elmah source, made some quick adjustments, and posted the solution to &lt;a href="http://code.google.com/p/elmah/issues/detail?id=148#c3"&gt;http://code.google.com/p/elmah/issues/detail?id=148#c3&lt;/a&gt;.  On the off chance that post gets deleted and to add more visibility to the simplicity to the solution, here's the patch file that shows the (not kidding) 14 lines that made this feature a reality.  If you like this patch too, log into Elmah's project site and "me too" comment to the ticket.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;diff -r 2482ebd0a4ae src/Elmah/ErrorLogModule.cs&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;--- a/src/Elmah/ErrorLogModule.cs    Tue May 01 19:31:20 2012 +0200&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+++ b/src/Elmah/ErrorLogModule.cs    Wed May 02 16:13:53 2012 -0700&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@@ -84,15 +84,21 @@&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         protected virtual void OnErrorSignaled(object sender, ErrorSignalEventArgs args)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;-            LogException(args.Exception, args.Context);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            string id = LogException(args.Exception, args.Context);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            if (!string.IsNullOrEmpty(id)) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+                args.ErrorId = id;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// Logs an exception and its context to the error log.&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+        /// &amp;lt;returns&amp;gt;ErrorId, may be null since not all errors are logged&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;-        protected virtual void LogException(Exception e, HttpContextBase context)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+        protected virtual string LogException(Exception e, HttpContextBase context)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            string id = null;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if (e == null)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 throw new ArgumentNullException("e");&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@@ -105,7 +111,7 @@&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             OnFiltering(args);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if (args.Dismissed)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;-                return;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+                return id;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             //&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // Log away...&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@@ -118,7 +124,7 @@&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 Error error = new Error(e, context);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 ErrorLog log = GetErrorLog(context);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 error.ApplicationName = log.ApplicationName;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;-                string id = log.Log(error);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+                id = log.Log(error);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 entry = new ErrorLogEntry(log, id, error);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             catch (Exception localException)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@@ -137,6 +143,8 @@&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if (entry != null)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 OnLogged(new ErrorLoggedEventArgs(entry));&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            return id;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;diff -r 2482ebd0a4ae src/Elmah/ErrorSignal.cs&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;--- a/src/Elmah/ErrorSignal.cs    Tue May 01 19:31:20 2012 +0200&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+++ b/src/Elmah/ErrorSignal.cs    Wed May 02 16:13:53 2012 -0700&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@@ -46,15 +46,19 @@&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             Raise(e, null);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;-        public void Raise(Exception e, HttpContextBase context)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+        public string Raise(Exception e, HttpContextBase context)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if (context == null)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 context = new HttpContextWrapper(HttpContext.Current);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             ErrorSignalEventHandler handler = Raised;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            ErrorSignalEventArgs args = new ErrorSignalEventArgs(e, context);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if (handler != null)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;-                handler(this, new ErrorSignalEventArgs(e, context));&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+                handler(this, args);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            return args.ErrorId;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public static ErrorSignal FromCurrentContext()&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@@ -154,6 +158,11 @@&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             get { return _context; }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+        /// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+        /// When you handle the signal, update this with the resulting ErrorId (if any)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+        /// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+        public string ErrorId { get; set; }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public override string ToString()&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             return Mask.EmptyString(Exception.Message, Exception.GetType().FullName);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;diff -r 2482ebd0a4ae src/Elmah/ErrorTweetModule.cs&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;--- a/src/Elmah/ErrorTweetModule.cs    Tue May 01 19:31:20 2012 +0200&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+++ b/src/Elmah/ErrorTweetModule.cs    Wed May 02 16:13:53 2012 -0700&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@@ -129,15 +129,20 @@&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         protected virtual void OnErrorSignaled(object sender, ErrorSignalEventArgs args)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;-            LogException(args.Exception, args.Context);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            string id = LogException(args.Exception, args.Context);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            if (!string.IsNullOrEmpty(id)) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+                args.ErrorId = id;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            }        &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// Logs an exception and its context to the error log.&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;-        protected virtual void LogException(Exception e, HttpContextBase context)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+        protected virtual string LogException(Exception e, HttpContextBase context)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            string id = null;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if (e == null)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 throw new ArgumentNullException("e");&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@@ -150,7 +155,7 @@&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             OnFiltering(args);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if (args.Dismissed)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;-                return;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+                return id;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             //&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // Tweet away...&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@@ -240,6 +245,8 @@&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 OnWebPostError(request, localException);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;+            return id;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         private void OnWebPostError(WebRequest request, Exception e)&lt;/span&gt;&lt;img src="http://robrich.org/aggbug/88.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2012/05/02/Elmah-return-the-ErrorId-from-Signal-Raise.aspx</guid>
            <pubDate>Wed, 02 May 2012 23:38:27 GMT</pubDate>
            <comments>http://robrich.org/archive/2012/05/02/Elmah-return-the-ErrorId-from-Signal-Raise.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/88.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Thinking in Git</title>
            <category>Tools</category>
            <category>Events</category>
            <link>http://robrich.org/archive/2012/04/27/Thinking-in-Git.aspx</link>
            <description>I had the great pleasure of presenting at SEVDNUG with my son this evening.  He was a wonderful asset, and a great star.  When we were all done, I think his was the bigger applause.  I look forward to presenting with him again.&lt;br /&gt;
&lt;br /&gt;
Our topic was &lt;a href="http://git-scm.com/"&gt;Git&lt;/a&gt;, the new hotness for version control.  &lt;br /&gt;
&lt;br /&gt;
The Abstract of the talk is:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;Have you ever looked at Git because it was trendy, but stumbled away dazed? Git isn't your father's source control system, but most of your knowledge of TFS, SVN, or other source control systems transfer over just fine. We'll take your existing knowledge of your Commit / Update VCS and we'll layer in the methodologies, tools, and communities that Git uses. What's the difference between pull and update? Isn't branching and merging dangerous? Can I get colored icons in Windows or Visual Studio? How do I contribute to a GitHub project? We'll graph Git's actions in blocks and compare it to git command results. You'll come away thinking in Git, ready to easily leverage the additional power.&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;Quite humbly, I think we rocked the house.&lt;/p&gt;
&lt;h3&gt;What is Git?&lt;/h3&gt;
Git's website has a pretty good (if a bit verbose) description of Git:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;"Git is a free &amp;amp; open source, distributed version control system designed to handle everything from small to very large projects with speed and efficiency. Every Git clone is a full-fledged repository with complete history and full revision tracking capabilities, not dependent on network access or a central server. Branching and merging are fast and easy to do."&lt;br /&gt;
&lt;/div&gt;
&lt;h3&gt;Git's Methodology&lt;/h3&gt;
Git really has two main tricks, and the focus of all our discussion is to explore in depth these things:&lt;br /&gt;
&lt;br /&gt;
1. Git has 4 repository locations: the working directory, the staging area, the local repository, and remote repositories.  Once you can visualize where your data is, Git is easy.&lt;br /&gt;
&lt;br /&gt;
2. Git's magic is just moving labels between nodes.  We may call them branches, tags, HEAD, etc, but it's just an identifier for a node to Git.  If you understand how your labels move as you commit, everything else is gravy.&lt;br /&gt;
&lt;h3&gt;History of Git&lt;/h3&gt;
Git was created by Linus Torvalds in 2005.  He's famous for a few other projects ... like Linux.  I heard it said once that Linus would take over the world -- perhaps not with Linux, perhaps instead with Git.&lt;br /&gt;
&lt;h3&gt;Where is Git used?&lt;/h3&gt;
Git is used by most major source control hosting firms, and has become a staple at most social coding avenues:&lt;br /&gt;
&lt;br /&gt;
1. &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt; is the quintessential Git hang-out.  It offers both open-source and private repositories (cost is quite reasonable), and really focuses on the social end of coding.  (It's hard to describe the atmosphere and wonderment that is GitHub.  You really need to try it to see it.)&lt;br /&gt;
&lt;br /&gt;
2. &lt;a href="http://bitbucket.org/"&gt;BitBucket&lt;/a&gt; is the mecca for Mecurial open-source projects, and now provides Git hosting.&lt;br /&gt;
&lt;br /&gt;
3. &lt;a href="http://www.codeplex.com/"&gt;CodePlex&lt;/a&gt; is the open-source hangout for Microsofties, and includes hosting for TFS, SVN, and most recently, Git.&lt;br /&gt;
&lt;br /&gt;
4. &lt;a href="http://sourceforge.net/"&gt;SourceForge&lt;/a&gt; is the old hub of open-source, originally for CVS, now known for SVN, and more recently, they've added support for Mercurial and Git.&lt;br /&gt;
&lt;br /&gt;
Want more evidence that Git is ubiquitous?  Go to Microsoft's uber-mecca for open-source -- to their project for MVC, Web API, and Razor at &lt;a href="http://aspnetwebstack.codeplex.com/"&gt;http://aspnetwebstack.codeplex.com/&lt;/a&gt;.  Now click on Source Code, and click Connection Instructions.  Ya know what you see?  A Git url.  No "or SVN".  No "or TFS".  Nope.  All you get is Git.&lt;br /&gt;
&lt;br /&gt;
Clearly Git is winning in the realm of version control systems.&lt;br /&gt;
&lt;h3&gt;Elements of Source Control Systems&lt;/h3&gt;
There are 4 main elements to a source control system:&lt;br /&gt;
&lt;br /&gt;
1. GUI Tools&lt;br /&gt;
&lt;br /&gt;
2. Command-line Tools&lt;br /&gt;
&lt;br /&gt;
3. Node Graph / Commit Log&lt;br /&gt;
&lt;br /&gt;
4. Storage Map&lt;br /&gt;
&lt;br /&gt;
Looking at these 4 elements in an SVN realm, we get something like the following:&lt;br /&gt;
&lt;br /&gt;
1. TortoiseSVN provides an excellent front-end for the pointy-clicky people.&lt;br /&gt;
&lt;br /&gt;
2. svn command line is great for power users and for automating and scripting things.&lt;br /&gt;
&lt;br /&gt;
3. svn log from either the command-line or TortoiseSVN, and you've got a great view of SVN's history.&lt;br /&gt;
&lt;br /&gt;
4. SVN has really two spots where code lives: the SVN Server, and your Working Directory.&lt;br /&gt;
&lt;br /&gt;
Here's a graph of the 4 spots in SVN:&lt;br /&gt;
&lt;br /&gt;
&lt;img width="966" height="721" src="/images/robrich_org/svn-parts.png" alt="svn parts" /&gt;&lt;br /&gt;
&lt;br /&gt;
Using those same quadrants, we can enumerate the toolset for Git in Windows:&lt;br /&gt;
&lt;br /&gt;
1. &lt;a href="http://code.google.com/p/gitextensions/"&gt;Git Extensions&lt;/a&gt; works great as a Git GUI.  &lt;a href="http://code.google.com/p/tortoisegit/"&gt;TortoiseGit&lt;/a&gt; does ok, but it forces us to look at Git as if it was a SVN repository.  The two can install seamlessly on the same box, playing nicely together.&lt;br /&gt;
&lt;br /&gt;
2. &lt;a href="http://msysgit.github.com/"&gt;msysGit&lt;/a&gt; is the Git engine and command-line tools, though &lt;a href="https://github.com/dahlbyk/posh-git"&gt;posh-git&lt;/a&gt; is an interesting PowerShell plugin.  Most every other tool either depends on or installs msysGit.&lt;br /&gt;
&lt;br /&gt;
3. kdiff3 comes with Git Extensions, and is a great way to browse git's commit history and node graph.&lt;br /&gt;
&lt;br /&gt;
4. Git's storage system includes four main sections:&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;1. The working directory -- the check-out folder in Windows&lt;br /&gt;
2. The staging area -- the code you're getting ready to commit&lt;br /&gt;
3. Your local repository -- this is where the majority of the meat is&lt;br /&gt;
4. Remote repositories -- places where you share the code -- you need not have these, or you could have lots of connections to remote repositories&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
The graph we used for git's parts looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;img width="966" height="721" alt="git parts" src="/images/robrich_org/git-parts.png" /&gt;&lt;br /&gt;
&lt;br /&gt;
Now let's spend a bit more time with the 4 storage areas in Git:&lt;br /&gt;
&lt;br /&gt;
Working directory we know from SVN, TFS, CVS, and other acronymed alphabets.&lt;br /&gt;
&lt;br /&gt;
We're familiar with "the server", but in this case "the server" is on our local machine -- the "local repository".  That's kinda weird, but kinda cool.  Now I can commit when I'm at a good stopping point, even if I'm not completely done with the task.  Ever get "code complete but untested" but want to save your progress but not break the build?  That's the local repository.&lt;br /&gt;
&lt;br /&gt;
The staging area is also a little weird.  Why would I have a place between my working, checked-out files and my repository?  Well, it allows you to commit parts of things without needing to commit the other parts of things.  In time, and with great skill and training, this allows you to commit part of the file if the other parts of it don't need to be committed yet.  It's a great place to build smaller, more purposeful commits.  Alternatively, you may find you don't need this, and you'll use the "just get it in already" or "-a" flag to the commit command.&lt;br /&gt;
&lt;br /&gt;
Remote repositories are the most curious.  We've got a distributed version control system where everyone has a copy of every commit.  I can push my changes to you when I'm ready -- as a big clump.  Or maybe I'll push them to the CI server.  Or maybe I'll push them to a colleague for code review before I commit to "the build".  Or maybe on a small project, I just keep my source tree alone on my machine and have no remotes.&lt;br /&gt;
&lt;br /&gt;
Everything but the "Remote Repositories" is on my local machine.  I can  do everything needed with these while on a plane -- without network  access.&lt;br /&gt;
&lt;br /&gt;
We now have the 4 parts of a source control system in Git.  It's not scary once you know how it works.&lt;br /&gt;
&lt;h3&gt;Git Commands&lt;/h3&gt;
We did a great job of showing the git commands and mapping their results in a node graph made of felt and string.  It was truly a performance, and to do justice, I'd need video.  We didn't tape our presentation, but &lt;a href="http://blip.tv/open-source-developers-conference/git-for-ages-4-and-up-4460524"&gt;http://blip.tv/open-source-developers-conference/git-for-ages-4-and-up-4460524&lt;/a&gt; is a similar video, and the one I used for the majority of the inspiration of this section of the demo.  Me and my son took a bit different route, but this video does very well.  "A non-cyclical graph node isn't scary when it looks like this."  He's holding up a tinker toy, I'm holding up felt and string.  The audience laughs, settles into their comfortable seats, and we're off to the races.&lt;br /&gt;
&lt;br /&gt;
Here's a summary of the Git commands and the learning we can get from each one.  Go download &lt;a href="http://code.google.com/p/msysgit/downloads/list"&gt;msysGit&lt;/a&gt;, install it, then open up a command prompt or Git shell and follow along.  If I'm commenting on one, I'll add "// &amp;lt;--" to highlight something.  Don't include these as you're typing the commands.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;Start it off:&lt;/span&gt;&lt;br style="text-decoration: underline;" /&gt;
&lt;span style="font-family: Courier New;"&gt;git init&lt;/span&gt; // &amp;lt;-- get the repository started; we typically copy an existing repository, but this is simpler for now&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;span style="text-decoration: underline;"&gt;Adding files:&lt;/span&gt;&lt;br /&gt;
Go create a file, add content to it, and substitute your file's name for "&lt;span style="font-family: Courier New;"&gt;&amp;lt;filename&amp;gt;&lt;/span&gt;", and leave off the &amp;lt; and &amp;gt;.&lt;br style="text-decoration: underline;" /&gt;
&lt;span style="font-family: Courier New;"&gt;git add &amp;lt;filename&amp;gt;&lt;/span&gt; // &amp;lt;--It stored the file in the repository right here&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git status&lt;/span&gt; // &amp;lt;-- it shows we're on the "master" branch (trunk in SVN speak), and that the file is in staging&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git commit -m "some message"&lt;/span&gt; // &amp;lt;-- it added the label "HEAD" to it here, "HEAD" means "working directory is here"&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git log&lt;/span&gt; // &amp;lt;-- each commit has a sha1 hash that uniquely identifies it&lt;br /&gt;
&lt;br /&gt;
The sha1 of each commit is a hash of:&lt;br /&gt;
1. The content of the objects&lt;br /&gt;
2. The hashes of the parent node(s)&lt;br /&gt;
&lt;br /&gt;
Add another file or two, and &lt;span style="font-family: Courier New;"&gt;git log&lt;/span&gt; starts looking pretty tasty ... and pretty verbose.&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git log --oneline --graph --decorate&lt;/span&gt; // &amp;lt;-- this shows the graph node lines, the first 1/2 dozen characters of the hash, and branch labels -- very, very handy.  After about the third or fourth time typing this, you too will make a shell alias or a batch file to do it easier.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;The .git directory:&lt;/span&gt;&lt;br style="text-decoration: underline;" /&gt;
So now that we have some nice content in the local repository, let's go pillaging through the .git folder.  This .git folder is the actual repository data.  There are quite a few tasty nuggets in here, and understanding how they work is very helpful.  Open a few in your favorite text editor.  But DON'T SAVE THEM!  Don't brick your git!  :D&lt;br /&gt;
&lt;br /&gt;
- open the HEAD file -- it's the sha1 of the commit that the HEAD label points to.&lt;br /&gt;
&lt;br /&gt;
- open a few files in the refs folder -- they're also text files that contain the sha1 of the position of the label that is their name.&lt;br /&gt;
&lt;br /&gt;
- look through the objects folder, and note that the first 2 digits of the sha1 is the folder, the rest of the sha1 is the file -- this is where the actual content is stored, zlib compressed.  Open this in a text editor, and you'll get some pretty zany zaph dingbats.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;Branching:&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In Git, by convention, most things are done in branches.  Branches are very, very cheap in git, they're just labels.  Let's experiment with branching and merging, and see why they aren't nearly the pain you've experienced wit non-distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git branch somebranch&lt;/span&gt; // &amp;lt;-- This creates the branch but doesn't switch to it&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git checkout somebranch&lt;/span&gt; // &amp;lt;-- This switches to it&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git status&lt;/span&gt; // &amp;lt;-- check that you're on the branch you thought you were on&lt;br /&gt;
now create a file, add it, and commit it&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git log --oneline --graph --decorate&lt;/span&gt; // &amp;lt;-- note that somebranch and HEAD moved, master didn't&lt;br /&gt;
&lt;br /&gt;
It's worth re-emphasizing that git's branches are just labels on nodes.  We didn't copy all the files when we branched, the repo is no bigger for having the branch.  It's merely another name for the node besides it's sha1 hash name.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;Merging (fast-forward):&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Merging is also no big deal in git.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git checkout master&lt;/span&gt; // &amp;lt;-- get back to master&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git merge somebranch&lt;/span&gt; // &amp;lt;-- merge somebranch into master&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git commit -m "merged somebranch"&lt;/span&gt; // &amp;lt;-- commit this change&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git log --oneline --graph --decorate&lt;/span&gt; // &amp;lt;-- note that master now moved to match somebranch and HEAD&lt;br /&gt;
&lt;br /&gt;
We just moved the label -- very simple.  The paths didn't diverge, so we needed only push the master label forward.  Gorgeous.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;Delete the Branch:&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In git, a branch is just a label.  If we don't need to refer to the commits by label anymore, we can remove the label.  It doesn't delete code, and we can always get back to the node by it's sha1 hash.  It merely removes the label from the node.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git branch -d somebranch&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;git log --oneline --graph --decorate&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;Branch / Merge (not fast-forward):&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git checkout -b branch1&lt;/span&gt; // &amp;lt;-- checkout -b creates the branch and switches to it in one shot&lt;br /&gt;
create a new file, add it, commit it&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git checkout master&lt;/span&gt; // &amp;lt;-- get back to before this new file was added&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git checkout -b branch2&lt;/span&gt; // &amp;lt;-- simulate a second developer &lt;br /&gt;
create another new file, add it, commit it&lt;br /&gt;
&lt;br /&gt;
We now have an interesting scenario: we have two "ends of the trail" -- two "tips".  So let's merge them together.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git checkout master&lt;/span&gt; // &amp;lt;-- get back to home base&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git merge branch1&lt;/span&gt; // &amp;lt;-- merge in the first branch&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git commit -m "merge branch1"&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;git merge branch2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;git commit -m "merge branch2"&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;git log --oneline --graph --decorate&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
See the nice diamond shape?  Pretty!  Try that with your silly little linear-only SVN.&lt;br /&gt;
&lt;br /&gt;
Also notice where your tags are.  HEAD and master are at the top of the graph, but branch1 and branch2 are still where they were.  We could merge this new master into them (fast-forward), but we probably don't need to.  More than likely, once this feature is done and integrated and enough time has passed, we can just delete these branch labels.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;Working with Remote Repositories:&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Now that we've got the hang of adding, committing, branching, and merging, and watched how it affects labels in our local repository, let's take a wander through how we can share this code with others.&lt;br /&gt;
&lt;br /&gt;
Create a new folder outside the previous folder.  Rather than &lt;span style="font-family: Courier New;"&gt;git init&lt;/span&gt; in this new folder, let's "initialize" this repository by linking to the previous repository.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git clone ../path/to/other/repo&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The "path" can be a windows file path, it can be an http url, it could be git://github.com/username/repo.git.  It doesn't matter where it came from, when we're done here, we have an exact duplicate of the other repository.  Prove this to yourself by running git log:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git log --oneline --graph --decorate&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
You've got all the history, all the tags, but something is interesting.  You've not only got your own HEAD and master labels, you've got some new labels: origin/master and origin/HEAD (and any other branches).  These new labels show you where the remote connection is.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git remote&lt;/span&gt; // &amp;lt;-- this one lists the remote links you've configured&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;git remote -v&lt;/span&gt; // &amp;lt;-- this one gives you the path to the other repository&lt;br /&gt;
&lt;br /&gt;
Now from here, we need to talk a little logistics.  In TFS or SVN land, we did update and commit.  Those two commands are the commands we use in Git when talking about transitioning from and to our working directory and local repository.  So what do we call it when we're moving between our local repository and a remote repository?  Pull and push.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git pull origin master&lt;/span&gt; // &amp;lt;-- get latest from them to my local repository&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;git push origin master&lt;/span&gt; // &amp;lt;-- send my latest changes to them&lt;br /&gt;
&lt;br /&gt;
If there's no major changes when I pull, I just commit to fast-forward my tags to the end of the line, and we're good to go.  If there were changes on both sides, I may need to resolve a conflict before merging.  Git gives me the standard "theirs", "mine", "fix it" -- both as diffs in command-line or as pretty diff compare views in GUI tools.  When I'm done, I commit, and it's now combined together.&lt;br /&gt;
&lt;br /&gt;
By convention, we'll probably want to designate one copy of the repository as "the master copy", and all push and pull to that one (unless unusual circumstances allow us to push and pull intermediary content between members of our team).  Though git technically doesn't need a "server to rule them all", it's always nice to have a central place where we can back up the corporate assets and where the CI / Build process can look to for "the latest and greatest".&lt;br /&gt;
&lt;h3&gt;Advanced Topics&lt;/h3&gt;
It wouldn't be fair to leave you in the dark about these advanced keywords that come in very handy.  Alas, it also wouldn't be fair for me to confuse you with these details while you're first learning git.  These tools are immensely handy though, and when you've got time, Google each of these terms:&lt;br /&gt;
&lt;br /&gt;
git reset&lt;br /&gt;
git rebase&lt;br /&gt;
git cherry pick&lt;br /&gt;
git stash&lt;br /&gt;
git flow&lt;br /&gt;
&lt;h3&gt;Bringing it Together&lt;/h3&gt;
We're now concluding where we began: Git has really two major things that differentiate it from the SVN / TFS methodology we're used to:&lt;br /&gt;
&lt;br /&gt;
1. Git has 4 repository locations: the working directory, the staging  area, the local repository, and zero or more remote repositories.  We saw how we could work with the staging area (&lt;span style="font-family: Courier New;"&gt;git add; git status&lt;/span&gt;), and in time we'll see how this view of the commit-in-embryo can be a great tool for forming cohesive, descriptive commits.&lt;br /&gt;
&lt;br /&gt;
2. Git's magic is just moving labels between nodes.  We saw throughout the command demos that as we made changes, we just created nodes and moved / added / removed labels from them.  These "branches" weren't expensive, they were just organizational tools.  If a "branch" node path doesn't work out, just abandon it, go back to master, and try again.  It's not a lock-step linear process where everyone inherits my mistakes.  It's just a system of nodes.&lt;br /&gt;
&lt;br /&gt;
Git can now be a very, very powerful tool.  Given the popularity and pervasiveness of git, I foresee it's just a matter of time before git is the new svn, and svn becomes the next cvs ... or worse, the next SourceSafe.  And if you learn nothing else from this presentation of "Thinking in Git", learn this: friends don't let friends use SourceSafe.  :D&lt;br /&gt;
&lt;h3&gt; Great Git Resources&lt;br /&gt;
&lt;/h3&gt;
&lt;a href="http://blip.tv/open-source-developers-conference/git-for-ages-4-and-up-4460524"&gt;http://blip.tv/open-source-developers-conference/git-for-ages-4-and-up-4460524&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://think-like-a-git.net/epic.html"&gt;http://think-like-a-git.net/epic.html&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://nfarina.com/post/9868516270"&gt;http://nfarina.com/post/9868516270&lt;/a&gt;&lt;img src="http://robrich.org/aggbug/87.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2012/04/27/Thinking-in-Git.aspx</guid>
            <pubDate>Fri, 27 Apr 2012 07:35:00 GMT</pubDate>
            <comments>http://robrich.org/archive/2012/04/27/Thinking-in-Git.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/87.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Sql Source Control from SSMS to Working Directory</title>
            <category>Tools</category>
            <link>http://robrich.org/archive/2012/04/25/Sql-Source-Control-from-SSMS-to-Working-Directory.aspx</link>
            <description>I use Sql Source Control in an unconventional way: I want to commit both sql scripts and code at once.  This means the CI server builds once with both sides.  This works very well if I can commit from Explorer using Tortoise.  It doesn't work so well when I commit from inside Visual Studio or from inside Sql Management Studio via Sql Source Control.&lt;br /&gt;
&lt;br /&gt;
Sql Source Control is basically Sql Compare between the database in Sql Server and something else, but built into Sql Management Studio -- a very excellent workflow.  What's really awesome: the "something else" (typically a source control system) could be anything.  They've built-in the ability to create my own command-line arguments for any source control system I have, then created the standard built-in configurations for the usual source control systems: TFS, SVN, Mercurial, and Git.  Well, what if my "source control command" was empty?  Now I'm scripting the database objects to the folder, and "committing" them to nothing.  Perfect.&lt;br /&gt;
&lt;br /&gt;
They recently added the ability to specify where the working directory is, so I place it in my sql folder right next to my src directory.  Push "fake-commit" in Sql Source Control, then the real commit can happen with the related code from Tortoise.&lt;br /&gt;
&lt;br /&gt;
It takes a bit of configuration, and I reached out to RedGate for clarity.  Here's the steps they directed me to, now immortalized, to make "database to working folder" work:&lt;br /&gt;
&lt;!--[if gte mso 9]&gt;&lt;xml&gt;
&lt;o:OfficeDocumentSettings&gt;
&lt;o:AllowPNG /&gt;
&lt;/o:OfficeDocumentSettings&gt;
&lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;
&lt;w:WordDocument&gt;
&lt;w:View&gt;Normal&lt;/w:View&gt;
&lt;w:Zoom&gt;0&lt;/w:Zoom&gt;
&lt;w:TrackMoves /&gt;
&lt;w:TrackFormatting /&gt;
&lt;w:PunctuationKerning /&gt;
&lt;w:ValidateAgainstSchemas /&gt;
&lt;w:SaveIfXMLInvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;
&lt;w:IgnoreMixedContent&gt;false&lt;/w:IgnoreMixedContent&gt;
&lt;w:AlwaysShowPlaceholderText&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;
&lt;w:DoNotPromoteQF /&gt;
&lt;w:LidThemeOther&gt;EN-US&lt;/w:LidThemeOther&gt;
&lt;w:LidThemeAsian&gt;X-NONE&lt;/w:LidThemeAsian&gt;
&lt;w:LidThemeComplexScript&gt;X-NONE&lt;/w:LidThemeComplexScript&gt;
&lt;w:Compatibility&gt;
&lt;w:BreakWrappedTables /&gt;
&lt;w:SnapToGridInCell /&gt;
&lt;w:WrapTextWithPunct /&gt;
&lt;w:UseAsianBreakRules /&gt;
&lt;w:DontGrowAutofit /&gt;
&lt;w:SplitPgBreakAndParaMark /&gt;
&lt;w:EnableOpenTypeKerning /&gt;
&lt;w:DontFlipMirrorIndents /&gt;
&lt;w:OverrideTableStyleHps /&gt;
&lt;/w:Compatibility&gt;
&lt;w:DoNotOptimizeForBrowser /&gt;
&lt;m:mathPr&gt;
&lt;m:mathFont m:val="Cambria Math" /&gt;
&lt;m:brkBin m:val="before" /&gt;
&lt;m:brkBinSub m:val="&amp;#45;-" /&gt;
&lt;m:smallFrac m:val="off" /&gt;
&lt;m:dispDef /&gt;
&lt;m:lMargin m:val="0" /&gt;
&lt;m:rMargin m:val="0" /&gt;
&lt;m:defJc m:val="centerGroup" /&gt;
&lt;m:wrapIndent m:val="1440" /&gt;
&lt;m:intLim m:val="subSup" /&gt;
&lt;m:naryLim m:val="undOvr" /&gt;
&lt;/m:mathPr&gt;&lt;/w:WordDocument&gt;
&lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;
&lt;w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267"&gt;
&lt;w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal" /&gt;
&lt;w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1" /&gt;
&lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2" /&gt;
&lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3" /&gt;
&lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4" /&gt;
&lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5" /&gt;
&lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6" /&gt;
&lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7" /&gt;
&lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8" /&gt;
&lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9" /&gt;
&lt;w:LsdException Locked="false" Priority="39" Name="toc 1" /&gt;
&lt;w:LsdException Locked="false" Priority="39" Name="toc 2" /&gt;
&lt;w:LsdException Locked="false" Priority="39" Name="toc 3" /&gt;
&lt;w:LsdException Locked="false" Priority="39" Name="toc 4" /&gt;
&lt;w:LsdException Locked="false" Priority="39" Name="toc 5" /&gt;
&lt;w:LsdException Locked="false" Priority="39" Name="toc 6" /&gt;
&lt;w:LsdException Locked="false" Priority="39" Name="toc 7" /&gt;
&lt;w:LsdException Locked="false" Priority="39" Name="toc 8" /&gt;
&lt;w:LsdException Locked="false" Priority="39" Name="toc 9" /&gt;
&lt;w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption" /&gt;
&lt;w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title" /&gt;
&lt;w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font" /&gt;
&lt;w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle" /&gt;
&lt;w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong" /&gt;
&lt;w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis" /&gt;
&lt;w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid" /&gt;
&lt;w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text" /&gt;
&lt;w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing" /&gt;
&lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading" /&gt;
&lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List" /&gt;
&lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid" /&gt;
&lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1" /&gt;
&lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2" /&gt;
&lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1" /&gt;
&lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2" /&gt;
&lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1" /&gt;
&lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2" /&gt;
&lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3" /&gt;
&lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List" /&gt;
&lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading" /&gt;
&lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List" /&gt;
&lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid" /&gt;
&lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1" /&gt;
&lt;w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision" /&gt;
&lt;w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph" /&gt;
&lt;w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote" /&gt;
&lt;w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote" /&gt;
&lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1" /&gt;
&lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2" /&gt;
&lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3" /&gt;
&lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4" /&gt;
&lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5" /&gt;
&lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6" /&gt;
&lt;w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis" /&gt;
&lt;w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis" /&gt;
&lt;w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference" /&gt;
&lt;w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference" /&gt;
&lt;w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title" /&gt;
&lt;w:LsdException Locked="false" Priority="37" Name="Bibliography" /&gt;
&lt;w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading" /&gt;
&lt;/w:LatentStyles&gt;
&lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 10]&gt;
&lt;style&gt;
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin:0in;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
&lt;/style&gt;
&lt;![endif]--&gt;&lt;br /&gt;
1) When linking a db to source control, chose "More... custom setup." on the left
&lt;p class="MsoPlainText"&gt;2) Click on the "Manage Config Files..."&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;3) Make a copy of the Template.xml file in that folder and rename it to "WorkingFolder.xml"&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;4) Edit this xml file so that the name corresponds to the filename (&amp;lt;Name&amp;gt;WorkingFolder&amp;lt;/Name&amp;gt;), so it appears correctly in the drop down&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;5) Save the WorkingFolder.xml file&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;6) Close and reopen the "Link to Source Control" dialog in SSMS&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;7) Choose "WorkingFolder" from the drop down and specify a working folder by browsing to where you want to write the .sql files to&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;8) Choose your model&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;9) Click link&lt;/p&gt;&lt;img src="http://robrich.org/aggbug/86.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2012/04/25/Sql-Source-Control-from-SSMS-to-Working-Directory.aspx</guid>
            <pubDate>Wed, 25 Apr 2012 21:28:25 GMT</pubDate>
            <comments>http://robrich.org/archive/2012/04/25/Sql-Source-Control-from-SSMS-to-Working-Directory.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/86.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Design Patterns for data persistence: Unit-of-Work Pattern and Repository Pattern</title>
            <category>Code</category>
            <link>http://robrich.org/archive/2012/04/18/Design-Patterns-for-data-persistence-Unit-of-Work-Pattern-and.aspx</link>
            <description>&lt;h3&gt;Design Patterns&lt;/h3&gt;
Design Patterns are names we give code constructs.  We're not usually inventing anything new, we're just giving a name for things we've always done.  You've probably been doing it this way forever, but you never knew what to call it, it was just "the way it's done".  Giving it a name is very powerful as it gives us a way to communicate about larger topics.  Yeah, we can talk about for-loop, if-block, but what about system architecture topics?  In the world of auto repair, they have names for their larger pieces: radiator, engine block, alternator.  How do you convey to someone how your Data Access tier or your Presentation tier works?  This is the magic of Design Patterns -- names for these common execution techniques.&lt;br /&gt;
&lt;br /&gt;
Today we'll discuss two common Design Patterns for working with data storage: the Unit-of-Work Pattern, and the Repository Pattern.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Unit-ofWork Pattern&lt;/h3&gt;
Microsoft really likes the Unit-of-Work Pattern, so most every sample you see coming out of their shops will include this pattern.  The general theory is you have a reference to a stateful link to your data store -- a Data Context -- that will queue up your queries and then execute all the steps at once within a transaction.  They'll either all succeed or they'll all fail.&lt;br /&gt;
&lt;br /&gt;
For example you're placing an order in an Order Entry system.  You may insert or update the Customer record, insert an Order header, insert one or more Order detail lines, perhaps update the product's available count.  You want all of these writes to either succeed together or all fail.  The theory goes that you don't want to get the first 2 lines of the order saved, but then error trying to write line #3 and fail to update the customer or product.  You want to be confident that all these steps will succeed or fail.&lt;br /&gt;
&lt;br /&gt;
A typical method that uses the Unit of Work Pattern would look like so:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public int SaveOrder(int CustomerId, List&amp;lt;OrderDetail&amp;gt; OrderLines) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    MyDataContext db = new MyDataContext();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Customer c = db.Customers.First( c =&amp;gt; c.ID == CustomerId );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Order o = new Order {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        OrderDate = DateTime.Now,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        CustomerId = CustomerId,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    };&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    c.LastOrderDate = o.OrderDate;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    db.Orders.Insert( o );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    db.OrderDetails.InsertRange( OrderLines );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    db.SaveChanges();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    return o.ID;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
You can always spot the Unit-of-Work pattern with it's tell-tale "now go do it" method -- in this case named "SaveChanges".&lt;br /&gt;
&lt;br /&gt;
I could refactor this into 2 or 3 methods, one that creates the order, one that updates the customer, and all the while hang onto that stateful Data connection until I finally complete that work unit.  These methods could call different stored procedures to do each step if need be.  But good, bad, or indifferent, I must keep track of my handle to my work package until I'm done, then I must specifically say "done".&lt;br /&gt;
&lt;br /&gt;
Why use the Unit-of-Work pattern rather than just running each query separately?  Because I'm confident that the entire work unit will either succeed or fail, I'll never get caught with an inconsistent data state.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Repository Pattern&lt;/h3&gt;
The Repository Pattern's focus is to create an abstraction between the data store and the application so the application doesn't need to think about how it's stored, only that this widget stores it.  The Repository is responsible for doing all the wackiness of connecting to the data store, opening the db connection, forming the query parameters, containing the open connection, etc.  A Repository class has methods that take in objects or parameters, and return either an object or a list of objects.  A Repository method doesn't do business logic outside of simple validation.  It just shims data to the data store.&lt;br /&gt;
&lt;br /&gt;
A typical class that uses the Repository Pattern would look like so:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public class CustomerRepository {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    public Customer GetById( int CustomerId ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        using ( MyDataContext db = new MyDataContext() ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            return (&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                from c in db.Customers&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                where c.ID == CustomerId&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                select c&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            ).FirstOrDefault();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    public void Save( Customer c ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        using ( MyDataContext db = new MyDataContext() ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            if ( c.ID &amp;lt; 1 ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                db.Add( c );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            } else {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                db.Update( c );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            db.SaveChanges(); // Sadly, Microsoft's ORM is Unit-of-Work&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            // so we're just saying "my unit is this method".&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br /&gt;
Usage of this class is pretty straight forward:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public void ChangeCustomerName( int CustomerId, string FirstName, string LastName ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    CustomerRepository r = new CustomerRepository(); // Since the Repository is stateless,&lt;br /&gt;
&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;    // &lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;this could be a property on this class rather than a new instance&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Customer c = r.GetById( CustomerId );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    c.FirstName = FirstName;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    c.LastName = LastName;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    r.Save( c );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Notice that the consuming class doesn't need to know if GetById() was a stored procedure, or used an XML file or called an external service.  It just asked for something, passing in simple parameters, and got back a result.&lt;br /&gt;
&lt;br /&gt;
Why use the Repository Pattern rather than just create an instance of the DataContext everywhere and just query stuff?  Here's a few reasons:&lt;br /&gt;
&lt;br /&gt;
1. We can easily evaluate data usage, and optimize queries and indexes, because all queries are very carefully defined in a specific section of the code.&lt;br /&gt;
&lt;br /&gt;
2. Data connections are opened and closed within the method, so no connections leak. (Yes, .net's connection pooling insures we're not actually hammering the db.)&lt;br /&gt;
&lt;br /&gt;
3. If we ever need to swap data access strategies (LinqToSql to Entity Framework for example), we likely replace the DataContext class, change the Repository methods to call the new Context's methods, but nothing else in the app needs to change.  OK, if your Data Access strategy requires your objects derive from something, you'll need to adjust that too.  But the beauty of things like Entity Framework Code First or NHibernate or Dapper is that your entity classes don't need to derive from anything funky -- they're just plain old C# objects.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;A composite Unit-of-Work and Repository Pattern&lt;/h3&gt;
Well we've painted a nice picture of each of the patterns and their benefits, but what if I want the best of both worlds?  What if I want to know everything in various tables and methods happens at once but I want that clean separation that the Repository gives me?  That turns out to be a pretty simple adjustment, though often it's overkill for the task at hand.  But most of the "Repository Pattern" samples from Microsoft will actually do it this way.&lt;br /&gt;
&lt;br /&gt;
Here's an example of the hybrid Unit-of-Work / Repository Pattern:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public class BaseRepository {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    public class UnitOfWorkHandle {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        internal MyDataContext db { get; set; }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    public UnitOfWorkHandle StartUnitOfWork() {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        return new UnitOfWorkHandle {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            db = new MyDataContext();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        };&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    public void FinishUnitOfWork() {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        db.SaveChanges();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;public class CustomerRepository : BaseRepository {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    public Customer GetById( UnitOfWorkHandle Handle, int CustomerId ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        return (&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            from c in Handle.db.Customers&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            where c.ID == CustomerId&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            select c&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        ).FirstOrDefault();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    public void Save( UnitOfWorkHandle Handle, Customer c ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        if ( c.ID &amp;lt; 1 ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            Handle.db.Add( c );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        } else {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            Handle.db.Update( c );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br /&gt;
This is pretty cool:&lt;br /&gt;
&lt;br /&gt;
1. The actual implementation details of my data access strategy is hidden (and thus easily replaceable)&lt;br /&gt;
&lt;br /&gt;
2. All the queries are clearly defined and easily auditable&lt;br /&gt;
&lt;br /&gt;
3. I'm confident that either everything will succeed or everything will fail&lt;br /&gt;
&lt;br /&gt;
It has some draw-backs though:&lt;br /&gt;
&lt;br /&gt;
1. Usage is pretty complex:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public void ChangeCustomerName( int CustomerId, string FirstName, string LastName ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    CustomerRepository r = new CustomerRepository();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    UnitOfWorkHandle h = r.StartUnitOfWork();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Customer c = r.GetById( h, CustomerId );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    c.FirstName = FirstName;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    c.LastName = LastName;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    r.Save( h, c );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    r.FinishUnitOfWork();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
2. If I forget to call &lt;span style="font-family: Courier New;"&gt;FinishUnitOfWork()&lt;/span&gt; absolutely nothing happens: no error, no warning, no data is saved, it just goes poof, and sadly, it's very easy to do.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Which to Use?&lt;/h3&gt;
Ultimately the choice of which Data Access Pattern you use (similarly to your decision of which ORM / data transport technology you use) depends on the situation.  Do you want clean separation of concerns between your tiers?  Do you need to know that everything is executed together?  Would you rather a simpler interface to getting data?  Some even argue that Microsoft's ORM tools are themselves the "Data Layer", and that any pattern that wraps it is wasteful.  Choose the strategy that gives you the best value for the needs of the project: speed of development, maintainable code, legible code, data access speed, etc.&lt;br /&gt;
&lt;br /&gt;
Rob&lt;img src="http://robrich.org/aggbug/85.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2012/04/18/Design-Patterns-for-data-persistence-Unit-of-Work-Pattern-and.aspx</guid>
            <pubDate>Thu, 19 Apr 2012 06:41:09 GMT</pubDate>
            <comments>http://robrich.org/archive/2012/04/18/Design-Patterns-for-data-persistence-Unit-of-Work-Pattern-and.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/85.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Demystifying Lambdas in C# 3.0</title>
            <category>Code</category>
            <link>http://robrich.org/archive/2012/04/17/Demystifying-Lambdas-in-C-3-0.aspx</link>
            <description>I've had this conversation a few times, so it seems natural that it'd evolve onto my blog in time.  The conversation typically goes like this: "There's this weird thing I don't get.  It looks like this: &lt;span style="font-family: Courier New;"&gt;x =&amp;gt; x &amp;lt; 6&lt;/span&gt; and like this: &lt;span style="font-family: Courier New;"&gt;Func&amp;lt;int,bool&amp;gt; p&lt;/span&gt;."  Why are these so magical?  How did they come to be?  That's what we'll look at here.&lt;br /&gt;
&lt;br /&gt;
Let's start by clearly defining Lambda.  It's a function pointer (for the C/C++ among us), or it's a short-hand way to define a method (for those of us without that much hair loss), and it grew out of C#'s delegates.  They just make it simpler to pass basic (and not so basic) logic to another procedure.&lt;br /&gt;
&lt;br /&gt;
In .NET 1.0, we had delegates.  &lt;a href="javascript:void(0);/*1334729724626*/"&gt;MSDN&lt;/a&gt; defines them as "a type that references a method" or put more simply "a function pointer".  Somewhere in my class definition, I'd create the delegate definition:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public delegate bool LessThanSixDelegate( int InputVar );&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Elsewhere in the class, I'd create the implementation method definition:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public bool MethodName( int InputVar ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    return InputVar &amp;lt; 6;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Then embedded in some method somewhere I would instantiate this delegate, referencing the &lt;span style="font-family: Courier New;"&gt;MethodName()&lt;/span&gt; function:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;LessThanSixDelegate methodPointerInstance = new LessThanSixDelegate( MethodName );&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Then I'd use the instance like so:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;methodPointerInstance( 12 );&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
That's .NET 1.0 code, and it's well worn, and quite verbose.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fast-forward a few years, and we're at .NET 2.0, and the latest hotness is "Anonymous Methods" -- basically delegates without all the pomp and circumstance:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;public delegate bool LessThanSixDelegate( int InputVar );&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;LessThanSixDelegate methodPointerInstance = delegate( int InputVar ) { return InputVar &amp;lt; 6; };&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
We're making great progress.  I still need the delegate definition, but I don't need to separate the method that does the work from the instance of the delegate.  I create an inline method -- an anonymous method -- because the method doesn't have a name, only the instance has a name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fast-forward to .NET 3.0, and we now have Lambdas.  The main goal is to get more terse, avoid redundant characters, and get rid of the delegate definition.  Now we can create the delegate definition and method implementation all at once as we instantiate the instance.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;var methodPointerInstance = ( int InputVar ) =&amp;gt; { return InputVar &amp;lt; 6; };&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
They needed a character to denote the difference between input parameters and method body, and to denote it as a quick-built delegate -- function pointer -- lambda.  The character of choice: "&lt;span style="font-family: Courier New;"&gt;=&amp;gt;&lt;/span&gt;", pronounced "such that".  My method is basically "take in an int InputVar, and calculate InputVar such that InputVar is less than 6."&lt;br /&gt;
&lt;br /&gt;
This is gorgeous, but there's still some redundancy.&lt;br /&gt;
&lt;br /&gt;
If the usage determines the input parameter's type, we don't need to specify it.  Let's simplify by removing it:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;var methodPointerInstance = ( InputVar ) =&amp;gt; { return InputVar &amp;lt; 6; };&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
If we have only one line in our method, we don't need the return or the curly braces.  Let's simplify it to just this:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;var methodPointerInstance = ( InputVar ) =&amp;gt; InputVar &amp;lt; 6;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
If we only have one input parameter, we can avoid the parens around it and we're left with this:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;var methodPointerInstance = InputVar =&amp;gt; InputVar &amp;lt; 6;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
If I want to name my input parameter "x" instead of "InputVar", I could yield this:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;var methodPointerInstance = x =&amp;gt; x &amp;lt; 6;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Gorgeously tiny, very sweet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Well, all these simplifications were completely optional.  These two lines are completely identical:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;var methodPointerInstance = ( int InputVar ) =&amp;gt; { return InputVar &amp;lt; 6; };&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;var methodPointerInstance = x =&amp;gt; x &amp;lt; 6;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I can also choose which of these simplifications I prefer, and leverage that syntax.&lt;br /&gt;
&lt;br /&gt;
Well, what if the assumptions we made while simplifying it don't hold true?  What if we have zero parameters?  Or we have more than one parameter?  Well, we can't leave off the parens then.  What if we have more than one line in our function?  Then we can't leave off the curly braces or return line.  Here's an example of each:&lt;br /&gt;
&lt;br /&gt;
Zero parameters:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;var methodPointerInstance = () =&amp;gt; 5 &amp;lt; 6;&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;Two parameters:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;var methodPointerInstance = ( Param1, Param2 ) =&amp;gt; Param1 &amp;lt; Param2;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Two line long method body:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;var methodPointerInstance = InputVar =&amp;gt; {&lt;br /&gt;
    int comparer = 6;&lt;br /&gt;
    bool result = InputVar &amp;lt; comparer;&lt;br /&gt;
    return result;&lt;br /&gt;
};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I could also choose to add back in any of the short-cut things that I had removed.  Definitely season to taste.  All else being equal though, I like typing less.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what of this construct: &lt;span style="font-family: Courier New;"&gt;Func&amp;lt;int,bool&amp;gt;&lt;/span&gt;?  That's just a short-cut way of generically specifying a delegate as a parameter into a method.  &lt;span style="font-family: Courier New;"&gt;Action&amp;lt;T,U,V&amp;gt;&lt;/span&gt; is that way too.  Func&amp;lt;&amp;gt; will always return the last parameter and take in all the rest as input parameters.  Action&amp;lt;&amp;gt; will always take in all the parameters and return type is void.  Let's see each in action:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;Func&amp;lt;int,bool&amp;gt; methodPointerInstance = InputVar =&amp;gt; InputVar &amp;lt; 6;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This "anonymous method pointer" takes in a single int, and returns a bool.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;Func&amp;lt;int,int,bool&amp;gt; methodPointerInstance = (Param1,Param2) =&amp;gt; Param1 &amp;lt; Param2;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This func takes in two int parameters and returns a bool.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;Action&amp;lt;int,bool&amp;gt; methodPointerInstance = (Param1,Param2) =&amp;gt; {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    if ( Param2 ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        DoIt(Param1);&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This action takes in two parameters and returns nothing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, now when the method signature intelisense pops up with &lt;span style="font-family: Courier New;"&gt;Func&amp;lt;int,bool&amp;gt; methodSignature&lt;/span&gt;, no need to run for the hills.  Just pass in &lt;span style="font-family: Courier New;"&gt;x =&amp;gt; x &amp;lt; 6&lt;/span&gt; -- a lambda that matches the delegate definition using this cool short-cut syntax.&lt;br /&gt;
&lt;br /&gt;
Lambdas are immensely powerful, and your existing skills in forming delegates to satisfy click event handlers already gives you the skills you need to leverage them.  At the end of the day, they're just function pointers.  Awesome.&lt;br /&gt;
&lt;br /&gt;
Rob&lt;img src="http://robrich.org/aggbug/84.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2012/04/17/Demystifying-Lambdas-in-C-3-0.aspx</guid>
            <pubDate>Wed, 18 Apr 2012 06:51:46 GMT</pubDate>
            <comments>http://robrich.org/archive/2012/04/17/Demystifying-Lambdas-in-C-3-0.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/84.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Configuring other IIS boxes in the web farm</title>
            <category>Code</category>
            <link>http://robrich.org/archive/2012/04/12/Configuring-other-IIS-boxes-in-the-web-farm.aspx</link>
            <description>Configuring the first IIS 7.x box is far easier than IIS 6 was, but configuring multiple web servers to behave identically can be a pain.  &lt;a href="javascript:void(0);/*1334251785153*/"&gt;Web Farm Framework&lt;/a&gt; (available in Web Platform Installer) can automatically synchronize things, but these settings change so rarely, and changes need to propagate immediately that I'd rather do this manually.  Well, constructing the 3rd or 4th or nth machine gets old.  Can we make this easier?  Most definitely we can.&lt;br /&gt;
&lt;br /&gt;
Back in the IIS 6 days, the "IIS Metabase" was a scary thing -- like modifying the registry or getting surgery.  Granted, we did this every day, but it was always daunting.  In IIS 7, the entirety of the IIS configuration details are in xml in C:\Windows\System32\inetsrv\config\applicationHost.config (unless they're overridden in each site's web.config).  How do you set up machine 2 to behave exactly as machine 1?  You diff the files and copy nodes.  Yeah, no more surgery.  Awesome.&lt;br /&gt;
&lt;br /&gt;
Ok, setting up IIS #2 isn't quite as simple as diffing the files, but it's pretty close.  Here's a rough checklist of things I do to make machine 2 function identically to machine 1:&lt;br /&gt;
&lt;br /&gt;
1. Install IIS on each machine&lt;br /&gt;
2. Install any plugins / extensions on each machine - typically this is merely a trip through &lt;a href="javascript:void(0);/*1334251986391*/"&gt;Web Platform Installer&lt;/a&gt;&lt;br /&gt;
3. Configure Machine 1 to be perfect&lt;br /&gt;
4. Backup C:\Windows\System32\inetsrv\config\applicationHost.config on both machines -- it's easy to mess up, and running without a safety net is bad&lt;br /&gt;
5. Diff C:\Windows\System32\inetsrv\config\applicationHost.config between the two machines, and begin noticing the differences&lt;br /&gt;
6. Copy changes from machine 1 to machine 2&lt;br /&gt;
7. Restart IIS or reboot (you probably haven't rebooted since installing Windows Updates) -- probably not essential, but best not to get started on the wrong foot&lt;br /&gt;
&lt;br /&gt;
As we're diffing applicationHost.config we'll see a few things that we can merge, and a few things that must stay different.  Let's look through a few sections:&lt;br /&gt;
&lt;br /&gt;
- &lt;span style="font-family: Courier New;"&gt;&amp;lt;configProtectedData&amp;gt;&lt;/span&gt; node has &lt;span style="font-family: Courier New;"&gt;AesProvider&lt;/span&gt; and &lt;span style="font-family: Courier New;"&gt;IISWASOnlyAesProvider&lt;/span&gt; nodes.  These include machine-specific details.  If you accidentally merge these details between the two machines, go to your backup and get the original details back.  I've never personally hosed a box by doing so, but I've also treaded very carefully here.&lt;br /&gt;
&lt;br /&gt;
- &lt;span style="font-family: Courier New;"&gt;&amp;lt;system.applicationHost&amp;gt;&amp;lt;applicationPools&amp;gt;&lt;/span&gt; node includes one node per app pool.  Do you always set them to 4.0, startMode="AlwaysRunning" or anything else interesting?  It isn't 3 or 5 clicks away, it's just a text file change now.  Be careful not to merge an identity password though -- it's machine-specifically encrypted.  Just merge in all the app pools from Machine 1 into place.&lt;br /&gt;
&lt;br /&gt;
- &lt;span style="font-family: Courier New;"&gt;&amp;lt;system.applicationHost&amp;gt;&amp;lt;sites&amp;gt;&lt;/span&gt; node includes one child &lt;span style="font-family: Courier New;"&gt;&amp;lt;site&amp;gt;&lt;/span&gt; node per website.  You can configure everything here just by adding attributes and child nodes.  Or add a complete site by merging in another &lt;span style="font-family: Courier New;"&gt;&amp;lt;site&amp;gt;&lt;/span&gt; node.  (Be careful to insure their &lt;span style="font-family: Courier New;"&gt;id=""&lt;/span&gt; are unique and that they reference an &lt;span style="font-family: Courier New;"&gt;applicationPool&lt;/span&gt; that exists.)  Just merge in all the sites from Machine 1 into place.&lt;br /&gt;
&lt;br /&gt;
- &lt;span style="font-family: Courier New;"&gt;&amp;lt;system.webServer&amp;gt;&amp;lt;globalModules&amp;gt;&lt;/span&gt; includes a list of all the httpModules installed into IIS.  Depending on what order you clicked the check-boxes while installing IIS or what order Web Platform Installer installed plugins, these may be in different orders between the machine.  Provided you don't add or remove nodes, you can reorder them for "cleanliness".&lt;br /&gt;
&lt;br /&gt;
- &lt;span style="font-family: Courier New;"&gt;&amp;lt;location path="..."&amp;gt;&lt;/span&gt; nodes at the bottom alter authentication protocols for each site.  You can do similar overloads in web.config, but if you configured it through IIS, they'll be here.  (Alternatively, if you configured it in Visual Studio, the details may only be in that site's web.config.)&lt;br /&gt;
&lt;br /&gt;
Do you have any other noteworthy nodes in your IIS applicationHost.config files?  Any other techniques for configuring IIS with ease?&lt;br /&gt;
&lt;br /&gt;
Enjoy!&lt;br /&gt;
&lt;br /&gt;
Rob&lt;img src="http://robrich.org/aggbug/83.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2012/04/12/Configuring-other-IIS-boxes-in-the-web-farm.aspx</guid>
            <pubDate>Thu, 12 Apr 2012 17:52:42 GMT</pubDate>
            <comments>http://robrich.org/archive/2012/04/12/Configuring-other-IIS-boxes-in-the-web-farm.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/83.aspx</wfw:commentRss>
        </item>
        <item>
            <title>The "real-time" web in ASP.NET MVC</title>
            <category>Code</category>
            <link>http://robrich.org/archive/2012/04/05/The-real-time-web-in-ASP-NET-MVC.aspx</link>
            <description>The "real-time" web is one of the holy grails of software development.  It's the notion that we can provide a native experience through a browser.  Users can click or touch buttons, get instant feedback, get app status updates, all without the dreaded postback.&lt;br /&gt;
&lt;br /&gt;
There are quite a few technologies that are starting to bring this to fruition, but like any new shiny tool, we need to use them with wisdom and purpose.  With this new hammer, everything may start to look like a nail.  Let's discuss the landscape of these tools within the context of ASP.NET MVC.&lt;br /&gt;
&lt;br /&gt;
Typically when we say "real-time", the go-to marketing answer is &lt;a href="javascript:void(0);/*1333667109243*/"&gt;SiglalR&lt;/a&gt; as it provides for a constant connection between browser and server, and thus allows the browser to receive events from the server as they happen, not necessarily on next timer tick.  (SignalR also has great support for falling back through a stack of technologies that accomplish similar effects: server-side events, long polling, comet, etc.)  This type of connection is perfect for things like chat apps where the events from server to client are randomly timed, and you have a few clients.&lt;br /&gt;
&lt;br /&gt;
However, with a constant connection from client to server comes problems with load balancing and scalability.  It's easy to overload your server with SignalR.  The premise of the web -- and why it generally scales so well -- is it generally is very short duration requests that are heavily cached.  For example, consider a server that can handle 1000 concurrent requests.  (Ok, maybe it's 100,000, maybe it's 10, the number is not important.)  Now imagine that instead of quickly connecting, getting the answer, and disconnecting, they instead stay connected.  Now imagine the 1001th user tries to log on, and the user gets an HTTP 503 because the server is too busy.  Oops.&lt;br /&gt;
&lt;br /&gt;
If either of the two conditions above don't apply -- either you have evenly spaced events or you have very many clients -- then SignalR is just asking for server pain, and you should create a short-poll app with just regular AJAX and &lt;a href="javascript:void(0);/*1333667204234*/"&gt;jQuery&lt;/a&gt;.  For example, if you're just updating a dashboard page's graphs, charts, and news feed with the server's current data for this second, then create a regular $.ajax(...) call every second with a recursive setTimeout() loop or use setInterval() (the latter is easier, the former is safer), and tell the server to cache the answer for 1/2 second by using an [OutputCache] attribute on the Action method or Controller class.  Therefore the clients all get the answer quickly and reliably, the server need only process it twice within the second, and the server that can handle only 1000 concurrent requests can now handle far more concurrent browsers than just 1000.&lt;br /&gt;
&lt;br /&gt;
Why output cache for 1/2 second instead of matching the client's 1 second?  Because if one client connects at time 0:00 and the next client connects at time 0:00.9, they'll get a second old result.  If this an acceptable data freshness, definitely set the [OutputCache] to 1 second.  If 5 or 15 seconds is acceptable, set both client and server there.  If 15 minutes is acceptably stale, set it there.  (Note that because we're discussing this timeout, probably it's best to store it somewhere configurable and tweak it over time.)  But understand an [OutputCache] of 1 minute means client 2 connecting at 0:59 will have 1 minute old data.&lt;br /&gt;
&lt;br /&gt;
So what do you pass from server to client?  Do you pass markup -- a partial view?  A JSON object?  A combination of the two?  How about an UpdatePanel, a PageMethod, and a timer control?  It completely depends on your comfort level with each technology, and the prioritization of speed of client processing vs. speed of network transfer vs. development time.  Almost without fail, an UpdatePanel and a timer will be the heaviest use of the network and browser, but will leverage almost no JavaScript skills.  In all but the rarest scenarios, it's bringing a nuke to a gun fight.  I prefer very concise JSON objects because it uses so little network bandwidth, which is probably the most limited resource, but it does require some descent JavaScript skills.  Your mileage may vary, and your skills and development timeframe may lead you to different preferences.&lt;br /&gt;
&lt;br /&gt;
Ultimately, the theme now-a-days in ASP.NET is the theme that's emerging here: there is no one right way, but rather there are many solutions that are all well supported.  The "&lt;a href="javascript:void(0);/*1333667423837*/"&gt;one ASP.NET&lt;/a&gt;" may be better termed "one basket of tools", each of which is appropriate for a different task and skillset, and inappropriate for others.  The day of the hammer searching for a nail is over.  Long live the hammer.&lt;br /&gt;
&lt;br /&gt;
Rob&lt;img src="http://robrich.org/aggbug/82.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2012/04/05/The-real-time-web-in-ASP-NET-MVC.aspx</guid>
            <pubDate>Thu, 05 Apr 2012 23:11:11 GMT</pubDate>
            <comments>http://robrich.org/archive/2012/04/05/The-real-time-web-in-ASP-NET-MVC.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/82.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Extending ASP.NET MVC</title>
            <category>Events</category>
            <link>http://robrich.org/archive/2011/11/17/Extending-ASP-NET-MVC.aspx</link>
            <description>It is my pleasure to speak tonight at the SEVDNUG about extending ASP.NET MVC.  This talk grew out of an impromptu talk I gave at Desert Code Camp 2011.2.  The speaker didn't show for a class titled "Real world MVC", so I took it and ran with it.&lt;br /&gt;
&lt;br /&gt;
In this talk we'll look at some common and some less-common extension points for ASP.NET MVC:&lt;br /&gt;
&lt;ul&gt;
    &lt;li&gt;Routes&lt;/li&gt;
    &lt;li&gt;Route Constraint&lt;/li&gt;
    &lt;li&gt;Html Helper&lt;/li&gt;
    &lt;li&gt;Action Filter&lt;/li&gt;
    &lt;li&gt;Value Provider&lt;/li&gt;
    &lt;li&gt;Action Result&lt;/li&gt;
    &lt;li&gt;Model Metadata Provider&lt;/li&gt;
    &lt;li&gt;Dependency Resolver&lt;/li&gt;
&lt;/ul&gt;
The goal is to keep your code DRY (Don't Repeat Yourself), and many of these tools make it much easier to centralize cross-cutting concerns.&lt;br /&gt;
&lt;br /&gt;
Grab the code and slides we'll work with from &lt;a target="_blank" href="/content/ExtendingMVC.zip"&gt;here&lt;/a&gt;.&lt;img src="http://robrich.org/aggbug/81.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2011/11/17/Extending-ASP-NET-MVC.aspx</guid>
            <pubDate>Fri, 18 Nov 2011 00:03:32 GMT</pubDate>
            <comments>http://robrich.org/archive/2011/11/17/Extending-ASP-NET-MVC.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/81.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Desert Code Camp 2011.2</title>
            <category>Events</category>
            <link>http://robrich.org/archive/2011/11/04/Desert-Code-Camp-2011-2.aspx</link>
            <description>Desert Code Camp is always such a pleasure, and I'm pleased to be able to speak twice this time.  I'm teaching two topics: Backbone and Qunit.&lt;br /&gt;
&lt;br /&gt;
Backbone is an MVC framework for JavaScript.  Much like you wouldn't stick your entire program in a click even handler, why would you stick all your client-side code in a jQuery click event handler?  Backbone gives you the structure to create well architected client-side code.  Backbone is also light enough and modular enough and not opinionated enough to get you quickly to an on-ramp.  Download the slides and sample code we'll play with &lt;a href="/content/backbone.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Qunit is the JavaScript unit test framework used by the jQuery team to test jQuery.  It is a great red/green test harness for doing very elegant testing of client-side business logic.  Download the slides and sample code we'll play with &lt;a href="/content/qunit.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
If you enjoyed this talk, leave me a comment.  If you didn't like it, tell me how I can do better.&lt;br /&gt;
&lt;br /&gt;
Rob&lt;img src="http://robrich.org/aggbug/80.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2011/11/04/Desert-Code-Camp-2011-2.aspx</guid>
            <pubDate>Sat, 05 Nov 2011 05:27:37 GMT</pubDate>
            <comments>http://robrich.org/archive/2011/11/04/Desert-Code-Camp-2011-2.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/80.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Web Forms to Razor</title>
            <category>Events</category>
            <link>http://robrich.org/archive/2011/07/28/Web-Forms-to-Razor.aspx</link>
            <description>I'm honored to present at SEVDNUG tonight.  Our topic is "Web Forms to Razor".  Our primary focus is getting familiar with the new mechanisms in Razor and MVC, and learning how we can transition a product from one platform to another.&lt;br /&gt;
&lt;br /&gt;
We'll run with the solution &lt;a href="/content/WebFormsToRazor.zip"&gt;here&lt;/a&gt;, comparing the Web project (MVC) to the WebForms project.  Both include identical functionality and look &amp;amp; feel.  When we're done, we'll have a good introduction to MVC concepts and in particular Razor concepts -- enough to begin you thinking.  Over the course of the evening, we'll reference Phil Hack's Razor Cheat Sheet found at &lt;a href="http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx"&gt;http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Razor and MVC provide a newer, cleaner mechanism for handling web scenarios.  The former paradigm of abstracting HTML and JavaScript away from us has gotten in the way.  MVC gives us a foundation for a clean separation of concerns where it matters, and Razor provides a format for cleanly rendering html.  It's a very elegant stack, and I hope you enjoy this evening's demo.&lt;br /&gt;
&lt;br /&gt;
Rob&lt;img src="http://robrich.org/aggbug/79.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2011/07/28/Web-Forms-to-Razor.aspx</guid>
            <pubDate>Thu, 28 Jul 2011 22:35:59 GMT</pubDate>
            <comments>http://robrich.org/archive/2011/07/28/Web-Forms-to-Razor.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/79.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>
