<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4214922889450630344</id><updated>2011-07-30T11:56:09.034-07:00</updated><category term='Personal'/><category term='SharePoint'/><category term='WF'/><category term='Visual Studio'/><category term='Asp.net'/><category term='ReSharper'/><category term='Alt.net'/><category term='IoC'/><category term='IIS'/><category term='Linq'/><category term='Databinding'/><category term='Software Development'/><title type='text'>Robin Clowers</title><subtitle type='html'>I'm an ASP.NET developer living and working in the Seattle area. I am passionate about working with smart people to solve problems.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-6702162273792625805</id><published>2010-08-16T18:05:00.001-07:00</published><updated>2010-08-18T19:03:45.290-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><title type='text'>Dependency Injection Patterns</title><content type='html'>&lt;p&gt;I had a twitter conversation a while back with &lt;a href="http://paulhammant.com/" target="_blank"&gt;Paul Hammant&lt;/a&gt; about different ways to use a IoC container.  Paul is one of the leads on PicoContainer, one of the Java containers.  It all started with him coming across the &lt;a href="http://commonservicelocator.codeplex.com/" target="_blank"&gt;Common Service Locator&lt;/a&gt;, which is an adapter to allow frameworks to leverage a container without forcing consumers to use a specific one.  He had a big problem with one part of the implementation, the &lt;a href="http://commonservicelocator.codeplex.com/SourceControl/changeset/view/63489#332683" target="_blank"&gt;ServiceLocator&lt;/a&gt; class.  This class is a static gateway to the container, and he pointed out this is the antithesis of dependency injection and inversion of control.  While this is true, there has to be at least one place (usual a few places) in your application that gets access to the container to inject everything else.  &lt;/p&gt;  &lt;p&gt;In asp.net, this is usually achieved  by storing your container in the ApplicationState dictionary, and then accessing it where it is needed.  This pattern ends up being recreated in every application that uses a container, so container authors hid this functionality behind a static gateway.  Is this a bad thing?  If used as intended, I don’t see much real difference between using a global dictionary and using a static gateway (in fact, you could argue that the gateway is cleaner).  Paul’s point; however, was that giving developers access to this static gateway will lead to it being used all sorts of places it shouldn’t.  In practice, I have seen applications where is happens to some extent, but in many cases it has more to do with the lack of DI support in asp.net.&lt;/p&gt;  &lt;p&gt;Paul proposed a way to control access to the container using packages in java.  I came up with something similar in .net, although I had to use a separate assembly to enforce separation.  For asp.net mvc, it boils down to putting your controller factory and other extension points in their own assembly, and wrapping the container to make the various resolution methods internal.  That way, they can only be used in this infrastructure assembly.  I am not crazy about having to wrap the container, but it’s not that much code:&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;public class ContainerWrapper
{
 public const string ContainerKey = "Container";
 Container container;

 public void InitializeContainer()
 {
     container = new Container();
     container.Configure(c =&amp;gt; c.Scan(s =&amp;gt;
     {
         s.WithDefaultConventions();
         s.AddAllTypesOf&amp;lt;IController&amp;gt;();
     }));

     HttpContext.Current.Application[ContainerKey] = this;
 }

 internal object GetInstance(Type type)
 {
     return container.GetInstance(type);
 }

 internal T GetInstance&amp;lt;T&amp;gt;()
 {
     return container.GetInstance&amp;lt;T&amp;gt;();
 }
}&lt;/pre&gt;
&lt;p&gt;This is example uses StructureMap, and is very simplistic.  In a real application you would probably want to scan for registries that would contain the registration logic (those would be in you main web assembly).  The ControllerFactory looks this:&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;public class StructureMapControllerFactory : DefaultControllerFactory
{
 protected override IController GetControllerInstance(
     RequestContext requestContext, Type controllerType)
 {
     var application = requestContext.HttpContext.Application;
     var container = (ContainerWrapper)application[ContainerWrapper.ContainerKey];
     return container.GetInstance(controllerType) as IController;
 }
}&lt;/pre&gt;
&lt;p&gt;A complete sample project showing this off is on &lt;a href="http://github.com/RobinClowers/Samples/tree/master/DependencyInjectionDemoMvc/"&gt;Github&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;So I’m curious about two things.  First, in your experience, do developers abuse service locators when they could be using dependency injection?  Second, would it help to hide the container in an infrastructure assembly, only exposing a the registration and base classes that access the container internally?&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-6702162273792625805?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/6702162273792625805/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=6702162273792625805' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/6702162273792625805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/6702162273792625805'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2010/08/dependency-injection-patterns.html' title='Dependency Injection Patterns'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-7573782304238668624</id><published>2010-01-19T14:57:00.000-08:00</published><updated>2010-08-10T18:07:57.915-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IIS'/><category scheme='http://www.blogger.com/atom/ns#' term='Asp.net'/><title type='text'>IIS 7.5 Required File System Premissions</title><content type='html'>To host a site on IIS 7.5, you need to grant the application pool account access and to the source files. By default this is set to ApplicationPoolIdentity, which is the built in system account IIS_IUSRS.  If you don't do this, you will get the following error:&lt;div&gt;&lt;blockquote&gt;HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;If you want to allow anonymous access to the site, you also need to grant the Anonymous user identity access to these files.  By default this is the build in system account IUSR. If you dont do this you will get this error:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;HTTP Error 401.3 - Unauthorized
You do not have permission to view this directory or page because of the access control list (ACL) configuration or encryption settings for this resource on the Web server..&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;Hopefully this saves someone else (and me!) time.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-7573782304238668624?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/7573782304238668624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=7573782304238668624' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/7573782304238668624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/7573782304238668624'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2010/01/iis-75-required-file-system-premissions.html' title='IIS 7.5 Required File System Premissions'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-1982834498505496707</id><published>2009-08-19T11:20:00.000-07:00</published><updated>2009-08-19T11:22:02.169-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><title type='text'>WebPart Notes</title><content type='html'>Here are some notes from building a SharePoint web part.
&lt;ul&gt;&lt;li&gt;It seems when you deploy a feature containing web parts, you still have to add it to the web part gallery for each site. &lt;/li&gt;&lt;li&gt;If you want to reference controls in the CONTROLTEMPLATES directory, you can use the virtual path ~/_controltemplates.&lt;/li&gt;&lt;li&gt;If your controls have a code behind that is strong named, you must fully qualify the Inherits attribute of the @Control directive. &lt;/li&gt;&lt;li&gt;To remove broken webparts from a page, add the query string ?contents=1 to the URL. (Via &lt;a href="http://sharepointinsight.blogspot.com/2008/06/remove-bad-or-broken-web-parts-from.html"&gt;http://sharepointinsight.blogspot.com/2008/06/remove-bad-or-broken-web-parts-from.html&lt;/a&gt;) &lt;/li&gt;&lt;li&gt;To disable friendly error messages (and see the yellow screen of death) &lt;/li&gt;&lt;ul&gt;&lt;li&gt;set the CallStack attribute of the SafeMode node to true &lt;/li&gt;&lt;li&gt;set CustomErrors mode attribute to Off &lt;/li&gt;&lt;li&gt;set debug attribute of the Compilation node to true &lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-1982834498505496707?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/1982834498505496707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=1982834498505496707' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/1982834498505496707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/1982834498505496707'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2009/08/webpart-notes.html' title='WebPart Notes'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-2048251509754446621</id><published>2009-08-19T11:17:00.000-07:00</published><updated>2009-08-19T11:20:15.761-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='WF'/><title type='text'>SharePoint Workflow Notes</title><content type='html'>&lt;p&gt;Here are some notes from my experience building a SharePoint state machine workflow.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;All fields delcared on the workflow object must be serializable type or marked nonSerializedAny activities before the workflow activated event will not have access to workflow properties &lt;/li&gt;
&lt;li&gt;Remember to remove dll's from the GAC when building, GAC'ed versions will supersede local versions &lt;/li&gt;
&lt;li&gt;Emailing from SharePoint requires the network service account to have local activation permission for "IIS WAMREG Admin Service" (a dcom service): &lt;a href="http://www.cleverworkarounds.com/2007/10/25/dcom-fun-with-sharepoint/"&gt;http://www.cleverworkarounds.com/2007/10/25/dcom-fun-with-sharepoint/&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;There is a bug in the delay activity, here are some patches: &lt;a href="http://blogs.msdn.com/sharepoint/archive/2008/07/15/announcing-availability-of-infrastructure-updates.aspx"&gt;http://blogs.msdn.com/sharepoint/archive/2008/07/15/announcing-availability-of-infrastructure-updates.aspx&lt;/a&gt;, &lt;a href="http://support.microsoft.com/kb/953630/"&gt;http://support.microsoft.com/kb/953630/&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;SetSate is not like a return, the rest of the activities in that phase will still execute &lt;/li&gt;
&lt;li&gt;You cannot have more than one list template in a feature &lt;/li&gt;
&lt;li&gt;Set workflow logging level use this command:
&lt;ul&gt;
&lt;li&gt;stsadm -o setlogginglevel -category "Workflow Infrastructure" -tracelevel verbose &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;To get and set timer settings use this command:
&lt;ul&gt;
&lt;li&gt;stsadm -o getproperty -pn job-workflow -url &lt;a href="http://localhost/"&gt;http://localhost/&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;stsadm -o setproperty -pn job-workflow -pv "Every 1 minutes between 0 and 59" -url &lt;a href="http://localhost/"&gt;http://localhost/&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;To allow unsigned powershell scripts to run use this command:
&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Set-ExecutionPolicy Unrestricted
&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h4&gt;Workflow Versioning
&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;There is no concept of versioning for Visual Studio created SharePoint workflows &lt;/li&gt;
&lt;li&gt;Instead, include the version in the feature path, name, description and workflow name and description &lt;/li&gt;
&lt;li&gt;Change the assembly version, and the version in each of the other places &lt;/li&gt;
&lt;li&gt;Deploy as a new feature &lt;/li&gt;
&lt;li&gt;Make sure the old workflow is marked "No new instances" after you associate the new version (this should be automatic) &lt;/li&gt;
&lt;li&gt;Based on this, it seems like workflows should be in their own features to allow for simpler versioning &lt;/li&gt;
&lt;li&gt;Delay activities were not working correctly &lt;/li&gt;
&lt;li&gt;Worked with MS Premier support for weeks to try and resolve this &lt;/li&gt;
&lt;li&gt;Resetting the SharePoint timer service made the delay activity work correctly &lt;/li&gt;
&lt;li&gt;When they are initialized in the designer, setting the value to something else in the initialize event does not work &lt;/li&gt;
&lt;li&gt;If you bind the timeout property to a dependency field then it can be set in the initialize timeout handler, much like SendEmailActivity properties &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-2048251509754446621?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/2048251509754446621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=2048251509754446621' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/2048251509754446621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/2048251509754446621'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2009/08/sharepoint-workflow-notes.html' title='SharePoint Workflow Notes'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-7726232504836508641</id><published>2008-11-26T19:11:00.000-08:00</published><updated>2008-11-26T19:12:04.700-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ReSharper'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><title type='text'>ReSharper Fails to Load with a Generic Error</title><content type='html'>&lt;p&gt;After installing Resharper 4.1 on Windows 2003 server, I got this message  when I start Visual Studio
2008: &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;The Add-in 'JetBrains ReSharper 4.1' failed to load or caused an 
exception. &lt;/p&gt; &lt;p&gt;Error Message: The system cannot find the file specified. &lt;/p&gt; &lt;p&gt;Error Number: 80070002&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I emailed JetBrains support and got a quick response.  It turns out my system  did not have Extensibility.dll installed in the GAC (Global Assembly Cache), and  ReSharper requires this dll to run.  &lt;/p&gt; &lt;p&gt;To figure this out, I opened explorer to the path "%windir%\assembly", which  brings up a shell extension that displays the contents of your GAC.&lt;/p&gt; &lt;p&gt;The fix was easy, I just had to find the dll, which is installed with Visual  Studio.  Once I knew the location, I opened the Visual Studio command prompt and  ran &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;gacutil /i  "C:\Program Files\Common Files\Microsoft  Shared\MSENV\PublicAssemblies"&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Hopefully this saves someone else some time.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-7726232504836508641?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/7726232504836508641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=7726232504836508641' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/7726232504836508641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/7726232504836508641'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2008/11/resharper-fails-to-load-with-generic.html' title='ReSharper Fails to Load with a Generic Error'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-3096564623706536659</id><published>2008-09-04T22:00:00.000-07:00</published><updated>2008-09-04T22:10:23.676-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Databinding'/><category scheme='http://www.blogger.com/atom/ns#' term='Asp.net'/><title type='text'>Making the ASP.NET DataGrid Usable</title><content type='html'>&lt;p&gt;If you have ever used an ASP.NET DataGrid (or GridView without a DataSource control), then you know there is a lot of boiler plate code needed.&amp;nbsp; The project I am working on right now has a bunch of grids that need to edit, add and page over a certain data type, so I we wanted to avoid duplicating all that code across every page.&amp;nbsp; &lt;/p&gt; &lt;p&gt;A little research and a prototype later, I came up with what I call the AutoGrid.&amp;nbsp; For the most part, it just handles the editing, paging and error handling internally.&amp;nbsp; Arguably more interesting is the fact that it is a generic control; I was under the impression that web controls could not have type parameters.&amp;nbsp; While this is technically true, there is a cool work around, which is detailed in a &lt;a href="http://weblogs.asp.net/leftslipper/archive/2007/12/04/how-to-allow-generic-controls-in-asp-net-pages.aspx" target="_blank"&gt;blog post&lt;/a&gt; by Eilon Lipton.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Basically, you need create a control with generic arguments, and whatever functionality you are after. Then to create another control to second control to be used in asp.net markup. It needs to inherits from the first control and have a string property for each generic argument.&amp;nbsp; Finally you override the ControlBuilder for your first control and construct your second control by passing the type arguments to a Type&amp;nbsp; instance of the generic control.&amp;nbsp; The code for the non-generic markup control is below:&lt;/p&gt;&lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;ControlBuilder&lt;/span&gt;(&lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;GenericControlBuilder&lt;/span&gt;))]
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;GenericGrid &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;AutoGrid&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Object&lt;/span&gt;&amp;gt;
{
  &lt;span style="color: blue"&gt;private string &lt;/span&gt;_objectType;

  &lt;span style="color: blue"&gt;public string &lt;/span&gt;ObjectType
  {
      &lt;span style="color: blue"&gt;get
      &lt;/span&gt;{
          &lt;span style="color: blue"&gt;if &lt;/span&gt;(_objectType == &lt;span style="color: blue"&gt;null&lt;/span&gt;)
          {
              &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;String&lt;/span&gt;.Empty;
          }
          &lt;span style="color: blue"&gt;return &lt;/span&gt;_objectType;
      }
      &lt;span style="color: blue"&gt;set
      &lt;/span&gt;{
          _objectType = &lt;span style="color: blue"&gt;value&lt;/span&gt;;
      }
  }
}&lt;/pre&gt;&lt;pre class="code"&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, it doesn't do much by itself.&amp;nbsp; The ControlBuilder is where the magic happens (this code is straight from Eilon's example):&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;GenericControlBuilder &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;ControlBuilder
&lt;/span&gt;{
  &lt;span style="color: blue"&gt;public override void &lt;/span&gt;Init(&lt;span style="color: #2b91af"&gt;TemplateParser &lt;/span&gt;parser, &lt;span style="color: #2b91af"&gt;ControlBuilder &lt;/span&gt;parentBuilder,
      &lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;type, &lt;span style="color: blue"&gt;string &lt;/span&gt;tagName, &lt;span style="color: blue"&gt;string &lt;/span&gt;id, &lt;span style="color: #2b91af"&gt;IDictionary &lt;/span&gt;attribs)
  {
&lt;strike&gt;&lt;/strike&gt;
      &lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;newType = type;

      &lt;span style="color: blue"&gt;if &lt;/span&gt;(attribs.Contains(&lt;span style="color: #a31515"&gt;"objecttype"&lt;/span&gt;))
      {
          &lt;span style="color: green"&gt;// If objecttype is specified, create a generic type that is bound
          // to that argument and then hide the objecttype attribute.
          &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;genericArg = &lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;.GetType(
              (&lt;span style="color: blue"&gt;string&lt;/span&gt;)attribs[&lt;span style="color: #a31515"&gt;"objecttype"&lt;/span&gt;], &lt;span style="color: blue"&gt;true&lt;/span&gt;, &lt;span style="color: blue"&gt;true&lt;/span&gt;);
          &lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;genericType = &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;AutoGrid&lt;/span&gt;&amp;lt;&amp;gt;);
          newType = genericType.MakeGenericType(genericArg);
          attribs.Remove(&lt;span style="color: #a31515"&gt;"objecttype"&lt;/span&gt;);
      }

      &lt;span style="color: blue"&gt;base&lt;/span&gt;.Init(parser, parentBuilder, newType, tagName, id, attribs);
  }
}&lt;/pre&gt;&lt;pre class="code"&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="font-family: georgia"&gt;The other thing that makes this work is an IoC container.  In this case I'm using &lt;a href="http://structuremap.sourceforge.net/" target="_blank"&gt;Structure Map&lt;/a&gt;, but any IoC would work.  The idea is that since the AutoGrid knows the type it is editing, it can ask for the appropriate data access class.  &lt;a href="http://www.lostechies.com/blogs/chad_myers/" target="_blank"&gt;Chad Myers&lt;/a&gt; helped me get the configuration right, using a custom TypeScanner:&lt;/span&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RepositoryConventionScanner &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;ITypeScanner
&lt;/span&gt;{
  &lt;span style="color: blue"&gt;public void &lt;/span&gt;Process(&lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;type, &lt;span style="color: #2b91af"&gt;Registry &lt;/span&gt;registry)
  {
      &lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;repoForType = GetGenericParamFor(type.BaseType, &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Repository&lt;/span&gt;&amp;lt;&amp;gt;));

      &lt;span style="color: blue"&gt;if &lt;/span&gt;(repoForType != &lt;span style="color: blue"&gt;null&lt;/span&gt;)
      {
          &lt;span style="color: blue"&gt;var &lt;/span&gt;genType = &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;IRepository&lt;/span&gt;&amp;lt;&amp;gt;).MakeGenericType(repoForType);
          registry
              .ForRequestedType(genType)
              .AddInstance(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ConfiguredInstance&lt;/span&gt;(type));
      }
  }

  &lt;span style="color: blue"&gt;private static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;GetGenericParamFor(&lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;typeToInspect, &lt;span style="color: #2b91af"&gt;Type &lt;/span&gt;genericType)
  {
      &lt;span style="color: blue"&gt;if &lt;/span&gt;(typeToInspect != &lt;span style="color: blue"&gt;null
          &lt;/span&gt;&amp;amp;&amp;amp; typeToInspect.IsGenericType
          &amp;amp;&amp;amp; typeToInspect.GetGenericTypeDefinition().Equals(genericType))
      {
          &lt;span style="color: blue"&gt;return &lt;/span&gt;typeToInspect.GetGenericArguments()[0];
      }

      &lt;span style="color: blue"&gt;return null&lt;/span&gt;;
  }&lt;/pre&gt;&lt;pre class="code"&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="font-family: georgia"&gt;Then in your Application_Start event, just tell Structure Map to run this scanner on your assembly:&lt;/span&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;StructureMapConfiguration
  &lt;/span&gt;.ScanAssemblies()
  .IncludeAssemblyContainingType&amp;lt;&lt;span style="color: #2b91af"&gt;GenericGrid&lt;/span&gt;&amp;gt;()
  .With(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RepositoryConventionScanner&lt;/span&gt;());&lt;/pre&gt;&lt;pre class="code"&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="font-family: georgia"&gt;I wrote this code for a pretty specific situation, your mileage may vary.  I would love to hear thoughts about this, if you care to see the whole solution you can get it &lt;a href="http://www.filefactory.com/file/1fb8fa/n/AutoGridSample_zip" target="_blank"&gt;here&lt;/a&gt;. &lt;/span&gt;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-3096564623706536659?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/3096564623706536659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=3096564623706536659' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/3096564623706536659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/3096564623706536659'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2008/09/making-aspnet-datagrid-usable.html' title='Making the ASP.NET DataGrid Usable'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-4335973126479761225</id><published>2008-06-25T20:55:00.000-07:00</published><updated>2008-06-25T20:57:32.485-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Databinding'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq'/><title type='text'>Linq To SQL Caching</title><content type='html'>&lt;p&gt;I ran into a weird behavior while trying out different usage patterns of Linq To SQL.  I noticed that some queries were not hitting the database!  Now I knew that Linq To SQL object tracking keeps cached copies of entities it retrieves, but my understanding was that it only used this for identity mapping and would never return stale results.  After some Googling and then looking at the internals of the System.Data.Linq.Table class with Reflector, I came to the conclusion that it was indeed returning its cached results.    This makes sense once you understand the way the data context works; I didn't realize the implications of object tracking.  Once an object has been retrieved once by a data context, its values will not be updated by the database.  This is key for the way optimistic concurrency support works in Linq to SQL, but if you are used to writing simple crud applications where you ignore concurrency it would be easy to overlook this.  &lt;/p&gt;  &lt;p&gt;On thing still puzzles me though, if I change my call from&lt;/p&gt;  &lt;pre class="code"&gt;context.Products;&lt;/pre&gt;&lt;p&gt; to &lt;/p&gt;&lt;pre class="code"&gt;context.Products.ToList();&lt;/pre&gt;&lt;p&gt;I would always hit the database.  It turns out that ToList calls GetEnumerator (which leads to a query being fired) whereas when I databind directly against the Table, it calls IListSource.GetList, which will return the cached table if it can.  Why wouldn't you query the database to check for new objects that might have been added to your results, and why couldn't the same query use the cache when I call ToList on it?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-4335973126479761225?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/4335973126479761225/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=4335973126479761225' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/4335973126479761225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/4335973126479761225'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2008/06/linq-to-sql-caching.html' title='Linq To SQL Caching'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-5294435416730261928</id><published>2008-06-18T18:14:00.000-07:00</published><updated>2008-06-20T22:56:46.592-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linq'/><title type='text'>Deferred Execution in Linq to SQL</title><content type='html'>&lt;p&gt;Just like the last post, this one is motivated by a &lt;a href="https://www.blogger.com/comment.g?blogID=4214922889450630344&amp;amp;postID=892965719237419004" target="_blank"&gt;comment&lt;/a&gt; I got from someone identified as merlin981. Since we seem to have a running dialog, do you have a blog or other online presence? In any case, I wanted to explain my understanding of how Linq to SQL uses deferred execution because merlin and I seemed to have a very different ideas. &lt;/p&gt;  &lt;p&gt;Let's take a look at a simple query like the one below.&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;var &lt;/span&gt;dbContext = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;TestDataContext&lt;/span&gt;();
&lt;span style="color:blue;"&gt;var &lt;/span&gt;result = &lt;span style="color:blue;"&gt;from &lt;/span&gt;x &lt;span style="color:blue;"&gt;in &lt;/span&gt;dbContext.Products
         &lt;span style="color:blue;"&gt;select &lt;/span&gt;x;&lt;/pre&gt;At this point, the query is just and expression tree. When you iterate over the the results, the following single query executes against the database:
&lt;pre&gt;SELECT [t0].[Id], [t0].[Name], [t0].[Price], [t0].[CategoryId]
FROM [dbo].[Product] AS [t0]&lt;/pre&gt;At this point, I can access the Id, Name and CategoryId of all the products that were in the the database without any other connections to the database. On the other hand, if you were to do something like this:
&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;foreach &lt;/span&gt;(&lt;span style="color:blue;"&gt;var &lt;/span&gt;product &lt;span style="color:blue;"&gt;in &lt;/span&gt;result)
{
  Response.Write(product.Category.Name);
}&lt;/pre&gt;&lt;p&gt;This block of code is going to hit the database once for each product. Obviously we want to avoid that, and there are several ways to do so. One is to return an anonymous type containing just the columns we need:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;var &lt;/span&gt;result = &lt;span style="color:blue;"&gt;from &lt;/span&gt;x &lt;span style="color:blue;"&gt;in &lt;/span&gt;dbContext.Products
         &lt;span style="color:blue;"&gt;select new
         &lt;/span&gt;{
             x.Name,
             CategoryName = x.Category.Name
         };

&lt;span style="color:blue;"&gt;foreach &lt;/span&gt;(&lt;span style="color:blue;"&gt;var &lt;/span&gt;product &lt;span style="color:blue;"&gt;in &lt;/span&gt;result)
{
    Response.Write(product.CategoryName);
}&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;This method will do an inner join and pull back just the columns we asked for. Another way is to specify load options for our original query:

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;var &lt;/span&gt;dbContext = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;TestDataContext&lt;/span&gt;();
dbContext.LoadOptions.LoadWith&amp;lt;&lt;span style="color: rgb(43, 145, 175);"&gt;Product&lt;/span&gt;&amp;gt;(p =&amp;gt; p.Category);
&lt;span style="color:blue;"&gt;var &lt;/span&gt;result = &lt;span style="color:blue;"&gt;from &lt;/span&gt;x &lt;span style="color:blue;"&gt;in &lt;/span&gt;dbContext.Products
         &lt;span style="color:blue;"&gt;select &lt;/span&gt;x;&lt;/pre&gt;&lt;p&gt;This tells the Linq to SQL Execution engine to load all the fields in the Category entity for each product. The generated SQL is below.&lt;/p&gt;&lt;pre&gt;SELECT [t0].[Id], [t0].[Name], [t0].[Price], [t0].[CategoryId], [t1].[Name] AS [Name2]
FROM [dbo].[Product] AS [t0]
INNER JOIN [dbo].[Category] AS [t1] ON [t1].[Id] = [t0].[CategoryId]&lt;/pre&gt;&lt;p&gt;I hope this has been a helpful example of how Linq To SQL uses deferred execution.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-5294435416730261928?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/5294435416730261928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=5294435416730261928' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/5294435416730261928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/5294435416730261928'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2008/06/deferred-execution-in-linq-to-sql.html' title='Deferred Execution in Linq to SQL'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-892965719237419004</id><published>2008-06-09T18:11:00.001-07:00</published><updated>2008-06-09T18:11:38.498-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq'/><title type='text'>Stored Procedures, a Best Practice?</title><content type='html'>&lt;p&gt;I just saw &lt;a href="http://www.blogger.com/profile/05516602905783627586"&gt;merlin981&lt;/a&gt;'s &lt;a href="http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;amp;postID=2482102627266714910" target="_blank"&gt;comment&lt;/a&gt; on my LINQ to SQL post, thanks for taking time to leave it!&amp;#160; That said, I think the term &amp;quot;Best Practice&amp;quot; is something of a misnomer here.&amp;#160; There has been &lt;a href="http://weblogs.asp.net/fbouma/archive/2003/11/18/38178.aspx" target="_blank"&gt;much&lt;/a&gt; &lt;a href="http://weblogs.asp.net/rhoward/archive/2003/11/17/38095.aspx" target="_blank"&gt;written&lt;/a&gt; on &lt;a href="http://codebetter.com/blogs/eric.wise/archive/2006/05/24/145393.aspx" target="_blank"&gt;both&lt;/a&gt;&amp;#160;&lt;a href="http://nhibernate.codebetter.com/blogs/jeremy.miller/archive/2005/07/06/130094.aspx"&gt;sides&lt;/a&gt; of this debate.&amp;#160; One thing is for sure, though, a parameterized query is compiled just like a stored procedure on SQL Sever version 7.0 and on.&amp;#160; From &lt;a href="http://weblogs.asp.net/fbouma/" target="_blank"&gt;Frans Bouma's blog&lt;/a&gt;, I found this &lt;a href="http://msdn.microsoft.com/en-us/library/aa174792.aspx" target="_blank"&gt;article&lt;/a&gt; in the SQL Server's Books Online:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;SQL Server 2000 and SQL Server version 7.0 incorporate a number of changes to statement processing that extend many of the performance benefits of stored procedures to all SQL statements. SQL Server 2000 and SQL Server 7.0 do not save a partially compiled plan for stored procedures when they are created. A stored procedure is compiled at execution time, like any other Transact-SQL statement. SQL Server 2000 and SQL Server 7.0 retain execution plans for all SQL statements in the procedure cache, not just stored procedure execution plans. &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;So I think it is clear that sprocs will not be significantly faster than ad hoc SQL for simple cases.&amp;#160; This is not to say that you should never use sprocs, on the contrary, there are situations where sprocs will be the only good solution (for instance, complex data manipulation that requires temporary tables). The point is that using an ORM can make development easier by allowing you to ignore the SQL for the majority of cases.&amp;#160; If you see that parts of your application are slow, then you can fix that. &lt;/p&gt;  &lt;p&gt;Merlin also mentioned that running queries directly against tables uses deferred execution like it is a bad thing.&amp;#160; Deferred execution is what allows LINQ to work at all, and can improve performance in many scenarios.&amp;#160; Of course, like any tool, it can get you into trouble if you don't understand it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-892965719237419004?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/892965719237419004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=892965719237419004' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/892965719237419004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/892965719237419004'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2008/06/stored-procedures-best-practice.html' title='Stored Procedures, a Best Practice?'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-2482102627266714910</id><published>2008-05-29T22:22:00.000-07:00</published><updated>2008-05-29T22:23:25.584-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq'/><title type='text'>Linq To SQL</title><content type='html'>&lt;p&gt;Linq to SQL is an object relational mapper (ORM) that is included in .NET 3.5.&amp;#160; The Linq to SQL designer allows you to create objects from you database tables simply by dragging the tables from the server explorer to the design surface.&amp;#160; You can customize the generated types in the designer or write code in partial classes.&amp;#160; Once you have defined your model, you can query it with Linq syntax and the SQL provider will generate the appropriate database calls for you.&lt;/p&gt;  &lt;p&gt;One limitation of Linq to SQL is a given object can only be populated from one table.&amp;#160; This means that your object will map almost one to one with your database tables.&amp;#160; For anything but the simplest applications, you don't want to work with the database tables.&amp;#160; For these situations, you could use Linq to SQL to populate domain objects.&amp;#160; Keep in mind that there is a performance overhead in creating these objects as opposed to using raw ADO.NET.&amp;#160; &lt;a href="http://blogs.msdn.com/ricom/" target="_blank"&gt;Rico Mariani&lt;/a&gt; has a good series of blog &lt;a href="http://blogs.msdn.com/ricom/archive/2007/06/22/dlinq-linq-to-sql-performance-part-1.aspx" target="_blank"&gt;posts&lt;/a&gt; about Linq to SQL performance, but I suggest profiling your application if you think it will be a problem.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-2482102627266714910?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/2482102627266714910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=2482102627266714910' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/2482102627266714910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/2482102627266714910'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2008/05/linq-to-sql.html' title='Linq To SQL'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-5138157265259514007</id><published>2008-05-15T20:05:00.000-07:00</published><updated>2008-05-15T20:06:56.555-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Databinding'/><category scheme='http://www.blogger.com/atom/ns#' term='Asp.net'/><title type='text'>ASP.NET 2.0 Databinding, Part III</title><content type='html'>&lt;p&gt;In &lt;a href="http://robinclowers.blogspot.com/2008/05/aspnet-20-databinding-part-i.html" target="_blank"&gt;part I&lt;/a&gt;, I covered datasource controls and two way databinding.&amp;#160; In &lt;a href="http://robinclowers.blogspot.com/2008/05/aspnet-20-databinding-part-ii.html" target="_blank"&gt;part II&lt;/a&gt;, I went into how to use table adapters for handling CRUD operations with two way binding.&amp;#160; Today I want to explain when it makes sense to use these features.&lt;/p&gt;  &lt;p&gt;It is important to keep in mind that any technology, feature or pattern will only be useful in a certain context.&amp;#160; Two way databinding is a good fit for single table editing scenarios in applications that will not get heavy user loads.&amp;#160; For more complex joined data you have to write code and it forces you into a very data centric and hard to test design.&amp;#160; For applications that have complex editing scenarios you are often better off handling the GridView events directly.&amp;#160; If you are designing a system with lots of business rules, you should probably using a rich domain model.&amp;#160; I intend to write a post about using domain driven design patterns soon.&amp;#160; &lt;/p&gt;  &lt;p&gt;By the same token, there are other options for handling data presentation.&amp;#160; Depending on you needs, you might want to consider using a commercial grid control like Telerik, Infragistics or Ext js.&amp;#160; Many of these controls will handle updating your datasource object for you, which gives you more freedom in the design of your data access strategy.&lt;/p&gt;  &lt;p&gt;If you found this series useful, saw a mistake or have any questions please let me know.&amp;#160; I am always interested in feedback, so feel free to leave me a comment.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-5138157265259514007?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/5138157265259514007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=5138157265259514007' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/5138157265259514007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/5138157265259514007'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2008/05/aspnet-20-databinding-part-iii.html' title='ASP.NET 2.0 Databinding, Part III'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-9100704865344681243</id><published>2008-05-05T23:32:00.000-07:00</published><updated>2008-05-05T23:35:11.111-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Databinding'/><category scheme='http://www.blogger.com/atom/ns#' term='Asp.net'/><title type='text'>ASP.NET 2.0 Databinding, Part II</title><content type='html'>&lt;p&gt;In &lt;a href="http://robinclowers.blogspot.com/2008/05/aspnet-20-databinding-part-i.html" target="_blank"&gt;part I&lt;/a&gt;, I talked about DataSource controls and how they enable two way databinding.  &lt;a href="http://msdn.microsoft.com/en-us/library/bz9tthwx.aspx" target="_blank"&gt;Table adapters&lt;/a&gt; are another new feature of ASP.NET 2.0 that was designed to work with the ObjectDataSource to allow declarative databinding.  &lt;/p&gt;  &lt;p&gt;What do I mean by declarative?  At a high level, declarative simply means you state what you want, not how you want it done (as opposed to imperative, where you say how something should be accomplished).  When these terms are applied to ASP.NET, it usually means aspx markup (declarative) or C# code in your code-behind classes (imperative).&lt;/p&gt;  &lt;p&gt;Table adapters generate ADO.NET code, specifically SqlDataAdapters and handles all the database connections for you.  Using the designer in Visual Studio we can drag and drop tables, specify stored procedures or ad-hoc SQL and VS will generate a strongly typed DataSet based on the shape of the query, and a SqlDataAdapter for each query you add.  &lt;/p&gt;  &lt;p&gt;The code that is generated by the designers are partial classes, so you can add methods and properties or handle events on the table adapters or the DataSets they return.  The usual example is adding validation logic, which is a nice idea, but implementing the validation with the ASP.NET validation controls generally provides a better user experience.  &lt;/p&gt;  &lt;p&gt;The table adapter classes and the query methods they expose are decorated with attributes that tell the databinding designers they support certain operations.  You could implement your own objects that can work with two way binding that persist to a completely different database, or call a set of web services.&lt;/p&gt;  &lt;p&gt;The first query you add to a table adapter defines the shape of the DataTable that is generated for you.  If this query is a single table select statements, the designer can generate the insert, update and delete methods for you, otherwise you must manually write the SQL.&lt;/p&gt;  &lt;p&gt;In part III, I will put the pieces together and look at where two way databinding and table adapters are a good fit.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-9100704865344681243?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/9100704865344681243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=9100704865344681243' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/9100704865344681243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/9100704865344681243'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2008/05/aspnet-20-databinding-part-ii.html' title='ASP.NET 2.0 Databinding, Part II'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-217381498549192957</id><published>2008-05-05T23:04:00.000-07:00</published><updated>2008-05-05T23:34:48.746-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Databinding'/><category scheme='http://www.blogger.com/atom/ns#' term='Asp.net'/><title type='text'>ASP.NET 2.0 Databinding, Part I</title><content type='html'>&lt;p&gt;This is the first of a series of posts about databinding in ASP.NET 2.0.  These posts are mostly for my understanding and writing practice, but hopefully someone gets value out of them as well.  To whoever does read this, I would love to hear some feedback.&lt;/p&gt;  &lt;p&gt;The features I will be talking about are covered in a &lt;a href="http://www.asp.net/learn/data-access/" target="_blank"&gt;set of tutorials&lt;/a&gt; by &lt;a href="http://scottonwriting.net/" target="_blank"&gt;Scott Mitchell&lt;/a&gt; that are much deeper and more detailed than these posts.  &lt;/p&gt;  &lt;p&gt;In ASP.NET 1.1, databinding was a manual, one way operation. You set the DataSource of a UI control to a collection and call DataBind. This is great, but what about getting the data back from the UI control? You have to manually access the values from the control and write code to map the values back to some kind of object.&lt;/p&gt;  &lt;p&gt;In ASP.NET 2.0, there is support for two way databinding. What do I mean by two way? When a command is issued to a bound control, it will check if the DataSource object it is bound to supports the given command. If it does, the data will be passed back to the datasource control which will handle the operation (update, insert, delete). &lt;/p&gt;  &lt;p&gt;This implementation has several parts. First, all data-bound controls now have a DataSourceID property. This property should correspond the ID property of a &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.datasourcecontrol.aspx" target="_blank"&gt;DataSourceControl&lt;/a&gt; object. These controls handle calling DataBind on the control and can be configured to handle most of the command events for a bound control (Edit, Update, Cancel, Delete, and Insert). Keep in mind that although DataSourceControl objects are part of the System.Web.UI namespace, they do not render anything themselves.&lt;/p&gt;  &lt;p&gt;For the datasource to work, you must at least configure it to handle fetching data. For an &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.objectdatasource.aspx" target="_blank"&gt;ObjectDataSource&lt;/a&gt;, this means pointing it to an instance method that it should call to fetch the data. For a &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.sqldatasource.aspx" target="_blank"&gt;SqlDataSource&lt;/a&gt;, you have to give it a connection string and a select statement.&lt;/p&gt;  &lt;p&gt;In part II, I will show how to use an ObjectDataSource in conjunction with TableAdapters (another ASP.NET 2.0 feature), to allow CRUD operations against a SQL Server database without writing a single line of C# code.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-217381498549192957?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/217381498549192957/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=217381498549192957' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/217381498549192957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/217381498549192957'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2008/05/aspnet-20-databinding-part-i.html' title='ASP.NET 2.0 Databinding, Part I'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4214922889450630344.post-4878915185892187250</id><published>2008-05-01T21:09:00.000-07:00</published><updated>2008-05-01T21:32:13.444-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Alt.net'/><category scheme='http://www.blogger.com/atom/ns#' term='Asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><title type='text'>Took the Plunge</title><content type='html'>I have been thinking about starting a blog for a while, so I am finally writing my first post.  I recently attended the alt.net open spaces in Seattle, and some conversations I had there made me decide to start a blog.

A little background;   I have been a computer geek since I was a kid, but I never did any amount of programming until I started college in 2003.  I have been working as an ASP.NET developer since January 2006, and I graduated from school in the beginning of 2007.

I'm not sure what the goal of this blog is yet, for the time being I am going to post problems I run into ( and hopefully resolve:-) ).  Hopefully other people will get some benefit from it as well, but if nothing else, it will be a good reference for me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4214922889450630344-4878915185892187250?l=blog.robinclowers.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.robinclowers.com/feeds/4878915185892187250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4214922889450630344&amp;postID=4878915185892187250' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/4878915185892187250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4214922889450630344/posts/default/4878915185892187250'/><link rel='alternate' type='text/html' href='http://blog.robinclowers.com/2008/05/took-plunge.html' title='Took the Plunge'/><author><name>Robin Clowers</name><uri>http://www.blogger.com/profile/09558658468617627887</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>
