<?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-6936017315111598402</id><updated>2012-01-19T01:19:15.622-08:00</updated><category term='ethics'/><category term='xml'/><category term='SQL'/><category term='patterns'/><category term='collaboration'/><category term='o/r-mapper'/><category term='SQL CLR'/><category term='Typed DataSets'/><category term='serialization'/><category term='BPM'/><category term='geek'/><category term='lambda'/><category term='sql server'/><category term='threading'/><category term='c#'/><category term='test'/><category term='WF'/><category term='.net 4.0'/><category term='ado.net'/><category term='identity'/><category term='practices'/><category term='abstraction'/><category term='web service'/><category term='Workflows'/><category term='performance'/><category term='split strings'/><category term='architecture'/><category term='basics'/><category term='utilities'/><title type='text'>Florian Reischl</title><subtitle type='html'>Things about Software Architecture, .NET development and SQL Server</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>38</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-7978652524324745891</id><published>2011-09-28T10:14:00.000-07:00</published><updated>2011-09-28T10:14:05.721-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='o/r-mapper'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='abstraction'/><title type='text'>Domain Objects And Many To Many Relations</title><content type='html'>Today I want to discuss different kinds of many to many relations and cases where it can make sense to transform them into different structures when they become loaded from a database into an object graph of a business layer. For sake of straightforwardness this post focuses on Microsoft Entity Framework and O/R-Mappers in general. Let me know, if one is interested in how to handle many to many relations in native ADO.NET.&lt;br/&gt;&lt;br/&gt;This is the third post of a blog series about designing domain objects in a business layer and the second part that gives attention to transformation of table structures into object structures. The first post "&lt;a href="http://florianreischl.blogspot.com/2011/09/tables-are-no-domain-objects-part-1.html"&gt;Tables Are No Domain Objects&lt;/a&gt;" gave an introduction to this series and showed some reasons why it can make sense to abstract O/R-Mappers in layers above the data access layer (DAL). In the second part "&lt;a href="http://florianreischl.blogspot.com/2011/09/tables-are-no-domain-objects-table.html"&gt;Tables Are No Domain Objects: Table Relation Transformations Part 1&lt;/a&gt;" we discussed foreign key fields, aggregations and status objects.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Basics&lt;/h3&gt;A many to many relation is given when two objects are related to each other and each of them can be referenced to more than one object (rows in the database) on the other side.&lt;br/&gt;&lt;br/&gt;An example for a many to many relation is the relation between &lt;i&gt;articles&lt;/i&gt; and their &lt;i&gt;categories&lt;/i&gt;. Each category can be related to many articles, like a category "food" that references apples, pies and meat. On the other hand, an article "apple" can be categorized as "food" and "healthy".&lt;br/&gt;&lt;br/&gt;In an object model a many to many relation is exposed by two domain objects where each contains a collection of objects of objects of the other type. Since databases don't provide complex column types, like &lt;i&gt;lists&lt;/i&gt; many to many relations are realized by putting an intermediate link table between the tables.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Simple Many To Many Relations&lt;/h3&gt;A simple many to many relation is given whenever the link table consists of nothing but the foreign keys which point to the rows of the two tables to be related to each other.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/ManyToManySimple.png"&gt;&lt;img width="650px" src="https://sites.google.com/site/florianreischl/blogspot-files/ManyToManySimple.png" alt="simple many to many relation" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br/&gt;When working with native ADO.NET many to many relations are always a bit tricky but can, for sure, be handled. I'll focus on O/R-Mappers for now.&lt;br/&gt;&lt;br/&gt;When working with a common O/R-Mapper simple many to many relations are usually automatically transformed by the mapper. The link table stays hidden inside of the mapper each of our two objects can provide a list of objects of the other type.&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public partial class Article {&lt;br /&gt;   public IList&amp;lt;Category&amp;gt Categories { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public partial class Category {&lt;br /&gt;   public IList&amp;lt;Article&amp;gt Articles { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The ORM knows all values to be inserted into our link table and doesn't need to annoy clients of our business layer with this table. If you are at the beginning of a project and your O/R-Mapper does not support simple many to many relations, I'd suggest to consider another mapper.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Complex Many To Many Relations&lt;/h3&gt;A complex many to many relation is given when the link table contains any additional columns which are not the foreign keys of our domain objects base tables.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/ManyToManyComplex.png"&gt;&lt;img width="650px" src="https://sites.google.com/site/florianreischl/blogspot-files/ManyToManyComplex.png" alt="complex many to many relation" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br/&gt;With this link table an O/R-Mapper like Entity Framework run into trouble. It is unable to fill our creation date column without an intermediate &lt;i&gt;domain object&lt;/i&gt; that does nothing but hold the additional column. Our two domain objects will look like this.&lt;br/&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public partial class Article {&lt;br /&gt;   public List&amp;lt;ArticleCategory&amp;gt; ArticleCategories { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public partial class Category {&lt;br /&gt;   public List&amp;lt;ArticleCategory&amp;gt; ArticleCategories { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;This might be fine for EF but usually that's not how we want to work with our objects in the main part of our system. Often columns like a creation date are only used for support or reporting purposes and we don't want to think about the odd &lt;i&gt;ArticleCategory&lt;/i&gt; object when adding new operations features.&lt;br /&gt;&lt;br /&gt;Without some refining of our domain objects we will be forced to implement every access of an articles categories like this.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;Article article = GetArticle();&lt;br /&gt;var categories = from acl in article.ArticleCategories&lt;br /&gt;                 select acl.Category;&lt;br /&gt;&lt;br /&gt;// process the article and its categories&lt;br /&gt;&lt;/pre&gt;It is not only unnatural to need to always access the intermediate object to get what we are really looking for but also a causes a tight coupling between our domain objects and the underlying database table structure. Worst thing would be if we started up with a simple many to many relation between articles and categories and a new requirement causes the need of the creation date column - and the resulting ArticleCategory object. Without some architectural effort we might have to refactor larger parts of our existing source code. Luckily, there are a few things we can do.&lt;br /&gt;&lt;br /&gt;The easiest way to hide the relation object is to define the &lt;i&gt;ArticleCategories&lt;/i&gt; property as &lt;i&gt;private&lt;/i&gt; and provide a few methods that give us the opportunity to directly work with the referenced entities.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;public partial class Article {&lt;br /&gt;   public IEnumerable&amp;lt;Category&amp;gt; GetCategories() {&lt;br /&gt;      return ArticleCategories.Select(acl =&amp;gt; acl.Category);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void AddCategory(Category category) {&lt;br /&gt;      ArticleCategory categoryLink = new ArticleCategory();&lt;br /&gt;      categoryLink.CreationDate = DateTime.Now;&lt;br /&gt;      categoryLink.Article = this;&lt;br /&gt;      categoryLink.Category = category;&lt;br /&gt;      ArticleCategories.Add(categoryLink);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void RemoveCategory(Category category) {&lt;br /&gt;      var categoryLink = ArticleCategories.Where(&lt;br /&gt;                           item =&amp;gt; category.Equals(item.Category)).FirstOrDefault();&lt;br /&gt;      if (categoryLink != null)&lt;br /&gt;         ArticleCategories.Remove(categoryLink);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;// =========================================&lt;br /&gt;// sample usage&lt;br /&gt;Article article = GetArticle();&lt;br /&gt;&lt;br /&gt;var categories = article.GetCategories();&lt;br /&gt;// process categories&lt;br /&gt;&lt;br /&gt;article.AddCategory(GetCateory());&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Apart from the fact that we provide a more natural access to our categories, this also causes an architecture that is robuster for possible future changes - like additional fields in our link table.&lt;br /&gt;&lt;br /&gt;If we want to go one step further we can provide an even more sophisticated interface to access our (indirectly) referenced domain objects. Unfortunately we cannot use a simple &lt;i&gt;List&amp;lt;T&amp;gt;&lt;/i&gt; and copy all categories into it because our ArticleCategories list would not become affected by any add/remove calls. This makes also impossible to use a simple LINQ query that transforms the &lt;i&gt;ArticleCategory&lt;/i&gt; objects into categories.&lt;br/&gt;&lt;br/&gt;However, what we can do is implement a custom &lt;i&gt;IList&amp;lt;T&amp;gt;&lt;/i&gt; that transforms a list of objects of one type into other objects by utilizing a provided delegate. In our case we need to transform a list of ArticleCategory objects into categories.&lt;br/&gt;&lt;br/&gt;The following snipped shows how such a list could work.&lt;br/&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;public class TransformationList&amp;lt;T, TResult&amp;gt; : IList&amp;lt;TResult&amp;gt; {&lt;br /&gt;   private IList&amp;lt;T&amp;gt; _list;&lt;br /&gt;   private Func&amp;lt;T, TResult&amp;gt; _transform;&lt;br /&gt;   private Func&amp;lt;TResult, T&amp;gt; _factory;&lt;br /&gt;&lt;br /&gt;   // Constructor that creates a read-only version of the list&lt;br /&gt;   public TransformationList(IList&amp;lt;T&amp;gt; list, &lt;br /&gt;                             Func&amp;lt;T, TResult&amp;gt; transformation)&lt;br /&gt;      : this(list, transformation, null) {&lt;br /&gt;   }&lt;br /&gt;   // Constructor that creates a writable version of the list&lt;br /&gt;   public TransformationList(IList&amp;lt;T&amp;gt; list, &lt;br /&gt;                             Func&amp;lt;T, TResult&amp;gt; transformation, &lt;br /&gt;                             Func&amp;lt;TResult, T&amp;gt; factory) {&lt;br /&gt;      _list = list;&lt;br /&gt;      _transform = transformation;&lt;br /&gt;      _factory = factory;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // Indexer access&lt;br /&gt;   public TResult this[int index] {&lt;br /&gt;      get { return _transform(_list[index]); }&lt;br /&gt;      set {&lt;br /&gt;         EnsureWritable();&lt;br /&gt;         _list[index] = _factory(value);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // Count property works like a proxy&lt;br /&gt;   public int Count { get { return _list.Count; } }&lt;br /&gt;&lt;br /&gt;   // The list is read-only if no factory method provided&lt;br /&gt;   public bool IsReadOnly { get { return _factory != null; } }&lt;br /&gt;&lt;br /&gt;   // Ensures that the list is writable and uses the factory method to create a new item&lt;br /&gt;   public void Insert(int index, TResult item) {&lt;br /&gt;      EnsureWritable();&lt;br /&gt;      _list.Insert(index, _factory(item));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // Read-only method uses the transformation method&lt;br /&gt;   public bool Contains(TResult item) {&lt;br /&gt;      return _list.Where(i =&amp;gt; item.Equals(_transform(i))).Any();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // ensure that the list is writable&lt;br /&gt;   private void EnsureWritable() {&lt;br /&gt;      if (IsReadOnly)&lt;br /&gt;         throw new InvalidOperationException("List is read only");&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // and so forth...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;The second constructor, which gets a second delegate as factory method makes the list writable and enables us to add new objects from outside without knowing that another, hidden object becomes materialized inside of our transformation list.&lt;br/&gt;&lt;br/&gt;This (reusable!) class makes us able to provide a our articles categories with a nice &lt;i&gt;IList&amp;lt;Category&amp;gt;&lt;/i&gt; property.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;public partial class Article {&lt;br /&gt;   private IList&amp;lt;Category&amp;gt; _categories;&lt;br /&gt;&lt;br /&gt;   public IList&amp;lt;Category&amp;gt; Categories {&lt;br /&gt;      get {&lt;br /&gt;         if (_categories == null)&lt;br /&gt;            _categories = &lt;br /&gt;               new TransformationList&amp;lt;ArticleCategory, Category&amp;gt;(&lt;br /&gt;                     ArticleCategories, &lt;br /&gt;                     (acl) =&amp;gt; acl.Category,&lt;br /&gt;                     (c) =&amp;gt; AddCategory(c));&lt;br /&gt;         return _categories;&lt;br /&gt;      }&lt;br /&gt;      set { _categories = value; }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public ArticleCategory AddCategory(Category category) {&lt;br /&gt;      ArticleCategory acl = new ArticleCategory();&lt;br /&gt;      acl.CreationDate = DateTime.Now;&lt;br /&gt;      acl.Article = this;&lt;br /&gt;      acl.Category = category;&lt;br /&gt;      ArticleCategories.Add(acl);&lt;br /&gt;      return acl;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;// =========================================&lt;br /&gt;// sample usage&lt;br /&gt;Article article = GetArticle();&lt;br /&gt;&lt;br /&gt;foreach (var category in article.Categories) {&lt;br /&gt;   // process categories&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;article.Categories.Add(GetCateory());&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;Simple many to many relations are usually easy to work with, but even if an O/R-Mapper shows some weakness in its mapping features, we are still able to provide a reasonable interface to clients of our business layer and its domain objects.&lt;br /&gt;&lt;h3&gt;Outlook&lt;/h3&gt;In the next part of this series we will look at version controlled data, what challenges they can could cause and ways to get them handled.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-7978652524324745891?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/7978652524324745891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2011/09/domain-objects-and-many-to-many.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7978652524324745891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7978652524324745891'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2011/09/domain-objects-and-many-to-many.html' title='Domain Objects And Many To Many Relations'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-2300983558251319644</id><published>2011-09-06T12:41:00.000-07:00</published><updated>2011-11-21T04:17:42.227-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='o/r-mapper'/><category scheme='http://www.blogger.com/atom/ns#' term='collaboration'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='abstraction'/><title type='text'>Tables Are No Domain Objects: Table Relation Transformations Part 1</title><content type='html'>This is the second part of a blog series '&lt;a href="http://florianreischl.blogspot.com/2011/09/tables-are-no-domain-objects-part-1.html"&gt;Tables Are No Domain Objects&lt;/a&gt;'. In this post we will discuss where database relations are good candidates to be accessed in a different manner when they are represented by domain objects of our business layer.&lt;br /&gt;&lt;br /&gt;The most obvious kind of a database table relation is a one (A) to many (B) relation where rows in table B hold a foreign key column that points to a unique key (usually the primary key) of table A. Most data access layers, based on an O/R-Mapper or custom mappings, do a good job to map this kind of database relations into objects, but there are some cases where it can make sense to transform those relations into a different structure or provide a different access than given by our database.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Foreign Key Fields And Transparent Database Relations&lt;/h3&gt;Before we step into more specific types of relations, there is one very basic thing where each of us should think about when starting to design a new business layer. In a database relations are always represented by foreign keys but when data are loaded into a object structure we can use object references, so we don't really need those foreign key fields as part of our objects. For instance, a sales order line object does not need to hold the ID of its parent sales order, it can hold a object reference of the sales order. One good reason to keep foreign key fields present our in domain objects is to have some additional logging and debugging information. However, we should never use those fields to implement any business logic on them, instead all business logic should always be implemented on the corresponding object references. &lt;i&gt;(Very rare exceptions prove the rule though.)&lt;/i&gt;&lt;br/&gt;&lt;br/&gt;This was already discussed in the previous blog post but should be recalled for sake of completeness. O/R-Mapper like Entity Framework or NHibernate provide a powerful query interface to access data, but using those queries in our business layer or presentation layers will cause a tight coupling between our source code and the database structure. Apart from other issues, discussed in the other post, queries like this can become a issue if we ever need to refactor our database structure or domain objects.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;var orders = from o in efContext.Orders&lt;br /&gt;             where o.CustomerId == currentCustomer.Id&lt;br /&gt;             select o;&lt;br /&gt;&lt;br /&gt;foreach (var order in orders) {&lt;br /&gt;   // process order&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Instead of this it is usually much safer to provide strong typed access methods out of our data access layer.&lt;br/&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;var orders = myDataContext.Orders.GetForCustomer(currentCustomer);&lt;br /&gt;&lt;br /&gt;foreach (var order in orders) {&lt;br /&gt;   // process order&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Please read the previous post (&lt;a href="http://florianreischl.blogspot.com/2011/09/tables-are-no-domain-objects-part-1.html"&gt;Tables Are No Domain Objects Part 1&lt;/a&gt;) to see further issues, especially when using Entity Framework.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Aggregations&lt;/h3&gt;In general I'm not as restrictive as other architects, who say it is always a bad solution to access any related objects of a current object reference, but when it comes to aggregations it can sometimes be dangerous to be done from outside of the class that holds the objects to be aggregated.&lt;br /&gt;&lt;br /&gt;One of the most common examples for a an aggregation that we should consider to encapsulate is when we have to calculate the price of a sales order that is based on the price of its line items.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;SalesOrder order = GetOrder();&lt;br /&gt;decimal orderPrice = &lt;br /&gt;   order.SalesOrderLines.Sum(line =&amp;gt; line.ArticlePrice * line.ItemCount);&lt;br /&gt;&lt;/pre&gt;From the very beginning of a new system this could work pretty nice. The problem is, what if the calculation of the sales orders price ever changes? Salespeople are creative to find new ways to sell the companies products and usually it is only a matter of time when discount features become required. Discounts can be a special offer for specific articles or article categories, a graduated discount depending on the orders all round price or many other types. Now we can run into trouble if we do a outside calculation of a sales orders price. A better solution is to put the aggregation into the sales order class.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public partial class SalesOrder {&lt;br /&gt;   public decimal GetPrice() {&lt;br /&gt;      return SalesOrderLines.Sum(line =&amp;gt; line.ArticlePrice * line.ItemCount);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;For now we only encapsulated the calculation that we have done from outside (what already avoids a duplication of logic to multiply with the sales lines item count) but when it comes to discounting we don't need to scan our whole source code to find all places where an orders price is calculated. We only have to adapt the body of our &lt;i&gt;SalesOrder.GetPrice&lt;/i&gt; method and the rest of the system doesn't even notice the new calculation.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;(The approach to do money calculations with decimal becomes part of a subsequent blog of this series.)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Status Objects&lt;/h3&gt;Status objects are special kinds of domain objects that describe the current status of their parent objects. They usually exist in a collaboration of their parent domain object and a description object that describes the current status.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/StatusObject.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://sites.google.com/site/florianreischl/blogspot-files/StatusObject.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;In addition to providing a current status of their parent object, status objects are often used to log an operational history of an object since they are usually not deleted or updated after their first creation. Since each new status object can change the state of its parent they are often very important rules for the processing of an object.&lt;br/&gt;&lt;br/&gt;As an example, say we have a parent &lt;i&gt;SalesOrder&lt;/i&gt; domain object that can hold a list of &lt;i&gt;SalesOrderStats&lt;/i&gt; objects where each of the status is described by a referenced &lt;i&gt;SalesOrderStatusDescription&lt;/i&gt; object. Now what if we want to know if an orders current status is "Closed"? Without some design effort we would have to do something like this.&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public partial class SalesOrderStatusDescription {&lt;br /&gt;   // status description code constants&lt;br /&gt;   public const string ClosedCode = "Closed";&lt;br /&gt;   // ...&lt;br /&gt;}&lt;br /&gt;// =========================================&lt;br /&gt;// sample usage&lt;br /&gt;SalesOrder order = GetOrder();&lt;br /&gt;&lt;br /&gt;bool isClosed = (from status in order.SalesOrderStatus&lt;br /&gt;                 where status.OrderId = order.Id&lt;br /&gt;                 orderby status.CreationDate descending&lt;br /&gt;                 select status.SalesOrderStatusDescription.Code)&lt;br /&gt;                 .First()&lt;br /&gt;                 == SalesOrderStatusDescription.ClosedCode;&lt;br /&gt;&lt;/pre&gt;Apart from the fact that this causes is tight coupling between three different domain objects and their base tables, it would be crap if we always would have to do so in upper layers, just to get an objects current state.&lt;br/&gt;&lt;br/&gt;A first thing we can do to prettify this is introduce an &lt;i&gt;enum&lt;/i&gt; that either represents the possible codes of our &lt;i&gt;SalesOrderStatusDescription&lt;/i&gt; objects or represents the possible foreign key values pointing to the &lt;i&gt;SalesOrderStatusDescription&lt;/i&gt; primary keys. Since we would need to always load the descriptions to parse the code fields, we will do the foreign key solution, what causes a lower database utilization. Yes, I know we should try to never base any functionality on foreign key values but I tend to see this as one of the valid exceptions. Our descriptions IDs are usually immutable and it does not make a big difference if our source code is coupled to the &lt;i&gt;Code&lt;/i&gt; column of the status description or its primary key.&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public enum SalesOrderStatusCode : int {&lt;br /&gt;   Created = 1,&lt;br /&gt;   Approved = 2,&lt;br /&gt;   Delivered = 3,&lt;br /&gt;   Payed = 4,&lt;br /&gt;   Closed = 5,&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Next step we can do is add a new property to our sales order status that represents the value of the enum. Unfortunately Entity Framework  does not provide native support for enums, so we need to do workaround by casting the foreign keys value.&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public partial class SalesOrderStatus {&lt;br /&gt;   public SalesOrderStatusCode Code {&lt;br /&gt;      get { return (SalesOrderStatusCode)SalesOrderStatusDescriptionId; }&lt;br /&gt;      set { SalesOrderStatusDescriptionId = (int)value; }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Okay, now we are able to shorten the previous snippet a little bit, but without one more method we would still need to traverse the list of all existing status whenever we want to know the current one. Since the current status of an object is usually a widely needed information we should add a method to our sales order that encapsulates the traversing returns the code of the current status.&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public partial class SalesOrder {&lt;br /&gt;   public SalesOrderStatusCode GetCurrentStatusCode() {&lt;br /&gt;      return (from status in SalesOrderStatus&lt;br /&gt;              orderby status.CreationDate descending&lt;br /&gt;              select status.Code)&lt;br /&gt;              .First();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;// =========================================&lt;br /&gt;// sample usage&lt;br /&gt;SalesOrder order = GetOrder();&lt;br /&gt;bool isClosed = order.GetCurrentStatusCode() == SalesOrderStatusCode.Closed;&lt;br /&gt;&lt;/pre&gt;This interface is much niftier and will make life much easier in client code.&lt;br/&gt;&lt;br/&gt;As an optional, last step we could add a &lt;i&gt;IsClosed&lt;/i&gt; method to our order. I use to do this only for the most important states of an object though.&lt;br/&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public partial class SalesOrder {&lt;br /&gt;   public bool IsClosed() {&lt;br /&gt;      return GetCurrentStatusCode() == SalesOrderStatusCode.Closed;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;// =========================================&lt;br /&gt;// sample usage&lt;br /&gt;SalesOrder order = GetOrder();&lt;br /&gt;bool isClosed = order.IsClosed();&lt;br /&gt;&lt;/pre&gt;Now our sales order provides a really handy interface that helps us to concentrate on other things when implementing features that need to work with the sales order status.&lt;br/&gt;&lt;br/&gt;Last but not least, we should add a corresponding method set the new status of an order.&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public partial class SalesOrder {&lt;br /&gt;   public void SetStatus(SalesOrderStatusCode code) {&lt;br /&gt;      SalesOrderStatus status = new SalesOrderStatus();&lt;br /&gt;      status.CreationDate = DateTime.Now;&lt;br /&gt;      status.Code = code;&lt;br /&gt;      status.SalesOrder = this;&lt;br /&gt;      SalesOrderStatus.Add(status);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;There is one line in this method that could cause problems. Setting the &lt;i&gt;CreationDate&lt;/i&gt; with by using the local hosts time is only safe if we are sure that all client PCs are configured with the same time server, otherwise we can get deflections of the creation date of new status. Since the creation date is essential for these objects this could cause issues in production. One thing we can do is to use the time from a central server, like the database server, instead of trusting the clients.&lt;br/&gt;&lt;br/&gt;Since there are usually much more places where we need to know the current status of an object than places where a status of an object becomes changed I tend to add less strong typed set methods like &lt;i&gt;SetPayed()&lt;/i&gt;.&lt;br/&gt;&lt;br/&gt;As we have seen, due to their importance and the complicated access, status objects are usually good candidates to be handled in a very different way than they are stored in our database and some architectural effort to get them into a more fashionable, object-oriented structure can be a good investment.&lt;br/&gt;&lt;br/&gt;&lt;span style="color: red"&gt;&lt;b&gt;Performance Tuning.&lt;/b&gt;&lt;/span&gt; Since this series concentrates on designing our domain objects I kept this until now, but our current solution requires to always retrieve all existing status objects from the database server, what causes a unneeded network traffic and database utilization. We should consider to add a method to our data access layer that loads only the current status, description ID or description code, instead of loading all status objects if not yet loaded anyway. This is another important reason why we should encapsulate the get method, since we need to change only one place.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Outlook&lt;/h3&gt;In the next post we will continue the discussion of table relation transformations.&lt;br/&gt;&lt;br/&gt;We will have a look at many to many relations where we might need to handle the weakness of O/R-Mappers.&lt;br/&gt;&lt;br/&gt;As last part of the discussion about table relation transformations we will have a look at versioned data.&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-2300983558251319644?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/2300983558251319644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2011/09/tables-are-no-domain-objects-table.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/2300983558251319644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/2300983558251319644'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2011/09/tables-are-no-domain-objects-table.html' title='Tables Are No Domain Objects: Table Relation Transformations Part 1'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-1377404471234238897</id><published>2011-09-01T14:12:00.000-07:00</published><updated>2011-10-01T06:16:13.334-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='o/r-mapper'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='abstraction'/><title type='text'>Tables Are No Domain Objects Part 1</title><content type='html'>This is the first part of a blog series where I want to discuss ways of how to design rich &lt;a href="http://en.wikipedia.org/wiki/Business_object"&gt;domain objects&lt;/a&gt; provided by the &lt;a href="http://en.wikipedia.org/wiki/Business_logic_layer"&gt;Business Logic Layer&lt;/a&gt; of a software system.&lt;br /&gt;&lt;br /&gt;In most business applications we have to work with data stored in a database or provided by web services. For sake of straightforwardness, we will focus on database based storages. However, when working with a skinny data web service layer that provides its data almost (or completely) in a database table style, some of the things we'll discuss here might still fit.&lt;br /&gt;&lt;br /&gt;Today where we are armed with shiny O/R-Mappers like NHibernate, Active Record or Microsoft Entity Framework. Some of those even provide a nice wizard that only needs a database connection to create a full set of &lt;i&gt;domain objects&lt;/i&gt;. It seems like we can immediately start to create our first front end dialog/view/page and use those classes.&lt;br /&gt;&lt;br /&gt;Cool, this "software architecture" and layering, people are talking about, is a wizard. Now we've got it. Thanks for participating the discussion, we are finished. Or, probably not... ;-)&lt;br /&gt;&lt;br /&gt;Sounds funny? Unfortunately quite a few applications are based on this kind of "software architecture" and "business layers". When talking about smaller projects, this might even work, but if a system becomes more complex, say with with some thousands lines of code (how about millions of lines?) this approach can become an early dead approach. A table-like domain object is often not perfect structured when we need to implement our business logic or when displaying in a rich presentation layer.&lt;br /&gt;&lt;br /&gt;Sure, we cannot cover everything that might need be considered when designing domain objects and structuring a business layer in a blog series, so we will concentrate on a few topics that I find more important and discuss some examples for each of them. At current stadium of software industry I don't even think that &lt;i&gt;anybody&lt;/i&gt; is at a point that (s)he knows &lt;i&gt;everything&lt;/i&gt; about architecting a business layer - or any other layer. If we look at the last 10 years of software industry we see way to many changes of minds. Every new pattern, technology or practice preaches itself to be the &lt;i&gt;golden calf&lt;/i&gt;. I'd say, as long as there is not a full decade without big changes in architectural and technical approaches, we will not know that we reached the end - and I guess we are far away from the beginning of this decade.&lt;br /&gt;&lt;br /&gt;With this knowledge about imperfection, we, still, should always do best to design a powerful and usable business layer. The business layer is the heart of all applications. It should encapsulate as much business logic as possible to avoid duplication of source code. After this encapsulation of logic, the highlight becomes to provide this logic by an easy to use interface for those (us?) who will consume it in a front end application like a windows UI or web UI, but also a web or windows services.&lt;br /&gt;&lt;br /&gt;Here is a short overview of the topics we will cover in this series.&lt;br /&gt;&lt;br/&gt;Before we dig deeper into designing of domain objects we will startup in this post with a look at &lt;b&gt;O/R-Mappers&lt;/b&gt;, if actually used, and reasons why we should consider to keep them inaccessible to other layers than our &lt;a href="http://en.wikipedia.org/wiki/Data_access_layer"&gt;Data Access Layer&lt;/a&gt;.&lt;br/&gt;&lt;br /&gt;In a following post we will talk about &lt;b&gt;Table Relations and Class References&lt;/b&gt;. We will look at database relations like aggregates or status objects that might be candidates to be represented in a different manner when they are loaded into a domain object hierarchy.&lt;br /&gt;&lt;br /&gt;When talking about &lt;b&gt;Field Aggregations&lt;/b&gt; I will try to show groups of database columns that can make sense to be arranged in referenced helper classes or structs instead of keeping them directly in our entities.&lt;br /&gt;&lt;br /&gt;We will discuss &lt;b&gt;Data Type Transformations&lt;/b&gt; and see some cases where it can be helpful when data, received from a database, are transformed into a different type or one database column can contain structural information.&lt;br /&gt;&lt;br /&gt;In the last part of this series we will talk about &lt;b&gt;Reusable Entities&lt;/b&gt;. There are some types of domain objects that appear in many projects. Some of them are good candidates to be implemented in base libraries reuse them in other projects, other types often appearing entities are harder or (almost) impossible to be reused.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How to Safely Use an O/R-Mapper&lt;/h3&gt;I know, this topic is not directly related to designing domain objects. However, since O/R-Mapper are often used as central component to access an underlying database this topic makes much sense to me to start with.&lt;br/&gt;&lt;br/&gt;We should always consider to abstract the native instance of the O/R-Mapper and I will try to show a few reasons here. First thing, when talking about designing domain objects, is we might run into architectural restrictions caused by restrictions of the ORM. If we directly use the mapper class in our whole system might not be able to design our objects as we would like to.&lt;br/&gt;&lt;br/&gt;Apart from the architectural reasons we should look a little closer at some other reasons why we should consider to avoid being tightly coupled with the O/R-Mapper.&lt;br/&gt;&lt;br/&gt;&lt;i&gt;(Examples and issues here are based on Microsoft Entity Framework. Some of them will also apply to other ORMs and others might not.)&lt;/i&gt;&lt;br/&gt;&lt;br/&gt;Let's do a jump start with a very simple domain model that contains only one entity &lt;i&gt;SalesOrder&lt;/i&gt;.&lt;br/&gt;&lt;br/&gt;&lt;div&gt;&lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/OrmAbstraction.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://sites.google.com/site/florianreischl/blogspot-files/OrmAbstraction.png"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;br/&gt;Here is a very simple example to use Microsoft Entity Framework with this domain model that already contains a few pitfalls.&lt;pre class="brush: csharp"&gt;&lt;br /&gt;using (var ctx = new Model1Container()) {&lt;br /&gt;   DateTime since = DateTime.Today.AddMonths(-1);&lt;br /&gt;   var orders = from o in ctx.SalesOrders&lt;br /&gt;                where o.CreationDate &amp;gt= since&lt;br /&gt;                select o;&lt;br /&gt;&lt;br /&gt;   foreach (var order in orders) {&lt;br /&gt;      // set approved&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // do something else&lt;br /&gt;&lt;br /&gt;   foreach (var order in orders) {&lt;br /&gt;      // create invoices&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;The worst issue of this piece of code is one that is especially related to the architecture of Entity Framework. The used LINQ query to get sales orders does actually not return a &lt;i&gt;real result&lt;/i&gt; of objects, instead it only returns an instance of an EF implementation of an &lt;i&gt;IQueriable&amp;lt;SalesOrder&amp;gt;&lt;/i&gt;. This IQueriable can be seen as an object version of a SQL statement, whenever we start to traverse through the result we will fire another database query. This causes unnecessary database load and (worse) can cause different results for each loop. If a new order becomes created between the first and the second &lt;i&gt;foreach&lt;/i&gt;-loop, we will get this order in our second loop and the order becomes invoiced before it was approved. A simple solution is to put the LINQ query into braces and call the &lt;i&gt;IEnumerable&amp;lt;T&amp;gt;.ToList()&lt;/i&gt; extension method. This copies the results into a &lt;i&gt;List&amp;lt;T&amp;gt;&lt;/i&gt; and all list operations become offline from now. Problem is, if we ever forget the call of ToList() we will again run into this trap.&lt;/br/&gt;&lt;br/&gt;A much safer way to use an O/R-Mapper is to create an own data storage class that wraps the EF container and provide custom methods for the needed data. At this point we stand on a crossroad where we have to decide between implementing a &lt;a href="http://martinfowler.com/eaaCatalog/gateway.html"&gt;Gateway&lt;/a&gt; (Martin Fowler, &lt;a href="http://martinfowler.com/eaaCatalog/"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt;) and provide all data access methods directly from our data storage class or implementing &lt;a href="http://martinfowler.com/eaaCatalog/repository.html"&gt;Repositories&lt;/a&gt; (Martin Fowler, PoEAA) for each of our domain object types. When working in smaller projects a Gateway is usually the better solution because it is easier to implement. Drawback of this pattern is, a Gateway class can become large when there are dozens or hundreds of access methods. The Repository approach needs more effort to be set up, since we need one for each type of domain object but keeps classes more well-arranged. Due to our large domain model I decided to use a Repository.&lt;br/&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;// Custom data store class that wraps the EF container&lt;br /&gt;public class DataStore : IDisposable {&lt;br /&gt;   private Model1Container _efContainer;&lt;br /&gt;   private SalesOrderRepository _salesOrders;&lt;br /&gt;      &lt;br /&gt;   public DataStore() {&lt;br /&gt;      _efContainer = new Model1Container();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public SalesOrderRepository SalesOrders {&lt;br /&gt;      get { return _salesOrders &lt;br /&gt;                   ?? (_salesOrders = new SalesOrderRepository(_efContainer)); }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void Dispose() {&lt;br /&gt;      _efContainer.Dispose();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;// ========================================================================&lt;br /&gt;// custom repository to provide access to sales orders&lt;br /&gt;class SalesOrderRepository {&lt;br /&gt;   Model1Container _efContainer;&lt;br /&gt;&lt;br /&gt;   internal SalesOrderRepository(Model1Container efContainer) {&lt;br /&gt;      _efContainer = efContainer;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public IEnumerable&amp;lt;SalesOrder&amp;gt GetCreatedSince(DateTime date) {&lt;br /&gt;      return (from o in _efContainer.SalesOrders&lt;br /&gt;               where o.CreationDate &amp;gt= date&lt;br /&gt;               select o).ToList();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;// ========================================================================&lt;br /&gt;// ========================================================================&lt;br /&gt;// sample usage&lt;br /&gt;using (var data = new DataStore()) {&lt;br /&gt;   DateTime since = DateTime.Today.AddMonths(-1);&lt;br /&gt;   var orders = data.SalesOrders.GetCreatedSince(since);&lt;br /&gt;&lt;br /&gt;   foreach (var order in orders) {&lt;br /&gt;      // set approved&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // will always be the same results&lt;br /&gt;   foreach (var order in orders) {&lt;br /&gt;      // create invoices&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;Now we need to remember only once that we need to add this odd ToList() method to avoid the previously described issues. Unfortunately this was only one, EF related, issue of directly accessing a O/R-Mapper from higher layers.&lt;br/&gt;&lt;br/&gt;Another issue is the &lt;i&gt;SalesOrder.IsCanceled&lt;/i&gt; property. In most parts of our software we might not want/need to work with canceled orders. Alike fields in other objects could be &lt;i&gt;IsActive&lt;/i&gt;, &lt;i&gt;IsDeleted&lt;/i&gt; and so forth. By encapsulating our O/R-Mapper we only need to change a few access methods to eliminate unwanted access to canceled orders. Sure, there are still parts of the system that might want to work with those orders but we should consider to provide them by more descriptive methods like &lt;i&gt;GetCreatedWithCanceledSince&lt;/i&gt; or simply &lt;i&gt;GetCanceledSince&lt;/i&gt;, depending on what is required.&lt;br/&gt;&lt;br/&gt;A non-abstracted O/R-Mapper access does usually also mean a tight coupling between our database and source code. If we ever need to change the structure of tables we can only hope that our ORM is able to handle the new structure without changing the domain model and, if it is able to handle the new mapping, we can hope that this will still give us the advantage that we aimed with our database changes. There can be database changes that will most likely make it impossible for most O/R-Mappers to stay able to handle them. Say we need to introduce some &lt;a href="http://ycmi.med.yale.edu/nadkarni/eav_cr_frame.htm"&gt;EAV/CR&lt;/a&gt; tables to move some rarely needed columns out of our main tables. When using a custom data store class we can relatively easy adopt an internal hybrid of keep using the ORM while doing other mappings with native ADO.NET features.&lt;br/&gt;&lt;br/&gt;What if not all data we need to work with come from our own database? I've just seen a thread MSDN Software Architecture Forums "&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/architecturegeneral/thread/556b5111-724d-4967-89ef-4853438b764b"&gt;&lt;u&gt;Centralizing Duplicate&lt;/u&gt; Functionality and &lt;u&gt;Data&lt;/u&gt;&lt;/a&gt;", where employees data had to be taken from one single source for all software systems of the company. Most O/R-Mapper support only one database but we can hold several different versions of them when working with a wrapping data storage class. Even if some of the data we work with are not provided by a database, say by a web service, we can still provide one homogeneous source of our data to the other layers.&lt;br/&gt;&lt;br/&gt;As a last reason for now why to abstract an O/R-Mapper we should keep the possibility of horizontal scaling in mind. With one database server we have only one option to get better performance from it, buying a bigger box. Though, there is a point where vertical scaling reaches its end. Most software systems consist of say 80% read and only 20% write operations. With a strong data access layer we are able to set up several read-only accessed database servers to handle all the read operations while all write operations are directed to the master server.&lt;br/&gt;&lt;br/&gt;There are still more reasons why we should consider to keep our O/R-Mapper inaccessible for main parts of the system but this might become part of another blog entry.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Upcoming Posts&lt;/h3&gt;I will add a link to all related posts here.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://florianreischl.blogspot.com/2011/09/tables-are-no-domain-objects-table.html"&gt;Tables Are No Domain Objects Part 2: Table Relation Transformations Part 1&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://florianreischl.blogspot.com/2011/09/domain-objects-and-many-to-many.html"&gt;Tables Are No Domain Objects Part 3: Domain Objects And Many To Many Relations&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Tables are no Domain Objects Part 4: Field Aggregations&lt;/li&gt;&lt;li&gt;Tables are no Domain Objects Part 5: Data Type Transformations&lt;/li&gt;&lt;li&gt;Tables are no Domain Objects Part 6: Reusable Entities&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/6936017315111598402-1377404471234238897?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/1377404471234238897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2011/09/tables-are-no-domain-objects-part-1.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/1377404471234238897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/1377404471234238897'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2011/09/tables-are-no-domain-objects-part-1.html' title='Tables Are No Domain Objects Part 1'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-6777418522230911370</id><published>2011-08-29T13:00:00.000-07:00</published><updated>2011-08-30T02:58:26.217-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server'/><category scheme='http://www.blogger.com/atom/ns#' term='ado.net'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='abstraction'/><title type='text'>Streaming SQL Server VARBINARY(MAX) In Chunks With ADO.NET</title><content type='html'>A few years ago it was unthinkable to store &lt;a href="http://en.wikipedia.org/wiki/Binary_large_object"&gt;BLOB&lt;/a&gt; data like large documents directly inside of a database. The most common way to store those large objects in combination with a database was to save the data to the file system and just store the UNC path in our database. Today storing BLOB data directly inside of a database became a common requirement in many projects. This new way to save binary data brings up a some advantages and drawbacks to think about.&lt;br/&gt;&lt;br/&gt;The probably most important advantage is security. If saving BLOB data in file system we not only have to manage security on database level but also restrict access to the file system, to avoid unauthorized access. Another advantage is integrity. A UNC file path, stored in a database becomes easily invalid if someone delete the file. This can happen by maleware attacks but also by bugs in a software that changes one side but not the other one. A file name doesn't provide any way to enforce referential integrity. Sometimes it is tricky to keep things synchronized, especially when working with transactions.&lt;br/&gt;&lt;br/&gt;On the other hand there is especially one drawback, when storing BLOBs inside of the database. If data are really large, say larger than 10MB or 100MB, it becomes tricky to save and read them without allocating huge amounts of data on server and client side. Where smaller data can easily be pushed or pulled in one chunk we don't want the client or server to handle 100MB as one big bunch of memory.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Missing Class in ADO.NET Framework?&lt;/h3&gt;On SQL Server 2008 when working with VARBINARY(MAX) based on &lt;a href="http://technet.microsoft.com/en-us/library/bb933995.aspx"&gt;FILESTREAM&lt;/a&gt; we can use the ADO.NET &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.sqltypes.sqlfilestream.aspx"&gt;SqlFileStream&lt;/a&gt; class to stream data from and to SQL Server. Unfortunately this class does not work if data are stored inside of a VARBINARY(MAX) column and not everyone wants to activate FILESTREAM - out of other reasons because of the integrity problem.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;SqlBinaryData Class&lt;/h3&gt;To become able to stream data stored in a VARBINARY(MAX) column, I wrote a helper class called &lt;i&gt;SqlBinaryData&lt;/i&gt; that provides a simple but powerful interface.&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public class SqlBinaryData : IBinaryData {&lt;br /&gt;   //...&lt;br /&gt;   &lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Creates a new readable instance of a &amp;lt;see cref="Stream"/&amp;gt; for the BLOB column&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;returns&amp;gt;A readable stream.&amp;lt;/returns&amp;gt;&lt;br /&gt;   public Stream OpenRead() {&lt;br /&gt;      return new SqlBinaryReader( // ...&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Creates a new writable instance of a &amp;lt;see cref="Stream"/&amp;gt; for the BLOB column&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;returns&amp;gt;A writable stream.&amp;lt;/returns&amp;gt;&lt;br /&gt;   public Stream OpenWrite(bool append) {&lt;br /&gt;      return new SqlBinaryWriter( // ...&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;Since the class works with four additional internal classes (about 700 lines of code) I will only focus on the most important parts here. You can find a ZIP archive containing the whole source code and my unit tests downloadable at the end of this post.&lt;br/&gt;&lt;br/&gt;The &lt;i&gt;OpenRead&lt;/i&gt; method creates an instance of an internal &lt;i&gt;SqlBinaryReader&lt;/i&gt; class that implements a readable version of a &lt;a href="http://msdn.microsoft.com/en-us/library/system.io.stream.aspx"&gt;System.IO.Stream&lt;/a&gt; and returns it to the consumer. The &lt;i&gt;OpenWrite&lt;/i&gt; method creates an instance of an internal &lt;i&gt;SqlBinaryWriter&lt;/i&gt; class that implements a writable version of &lt;i&gt;System.IO.Stream&lt;/i&gt; and returns it. The other two classes, &lt;i&gt;SqlBinaryInfo&lt;/i&gt; and &lt;i&gt;SqlBinaryMetaData&lt;/i&gt; are primary used to provide database connections, handle possible SQL injections and provide metadata.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Metadata Evaluation And Caching&lt;/h3&gt;Metadata, like primary key column and table names are established from SQL Server when first needed. The first time when this data is needed is when a stream becomes read or written. Until this there will be no database connection opened to avoid unnecessary resource allocation and database utilization.&lt;br/&gt;&lt;br/&gt;All metadata are cached for the current application domain. If an instance of a &lt;i&gt;SqlBinaryData&lt;/i&gt; needs database metadata that have already been established for the same table, binary column and connection string this information will be reused from an internal cache. If metadata for an unknown binary column is requested from two threads it is possible that one of the threads becomes suspended until metadata are allocated by the second thread. This will likely not cause any problems but should be known.&lt;br/&gt;&lt;br/&gt;If a database schema might change over the life time of a process and the primary key column becomes changed by name or type it is possible to clear the internal cache by calling the static method &lt;i&gt;SqlBinaryData.ClearMetaDataCache()&lt;/i&gt;. A reading or writing stream that is already active while the cache becomes cleared will keep working with its previously requested metadata what might cause an error, any new creation of a stream, even from an already existing &lt;i&gt;SqlBinaryData&lt;/i&gt; instance causes a reload of metadata from database.&lt;br/&gt;&lt;br/&gt;Metadata are allocated by utilizing SQL Server &lt;i&gt;INFORMATION_SCHEMA&lt;/i&gt; views, so should be accessible with most common database user rights.&lt;br/&gt;&lt;br/&gt;Table and schema name are taken, and so validated, from &lt;i&gt;INFORMATION_SCHEMA.TABLES&lt;/i&gt; view.&lt;pre class="brush: sql"&gt;&lt;br /&gt;-- If table schema is specified&lt;br /&gt;SELECT QUOTENAME(TABLE_NAME), QUOTENAME(TABLE_SCHEMA), TABLE_SCHEMA&lt;br /&gt;FROM INFORMATION_SCHEMA.TABLES&lt;br /&gt;WHERE TABLE_NAME = @tableName&lt;br /&gt;   AND TABLE_SCHEMA = @schemaName&lt;br /&gt;&lt;br /&gt;-- If table schema is not specified&lt;br /&gt;SELECT QUOTENAME(TABLE_NAME), QUOTENAME(TABLE_SCHEMA), TABLE_SCHEMA&lt;br /&gt;FROM INFORMATION_SCHEMA.TABLES&lt;br /&gt;WHERE TABLE_NAME = @tableName&lt;br /&gt;   AND TABLE_SCHEMA = OBJECT_SCHEMA_NAME(OBJECT_ID(@tableName))&lt;br /&gt;&lt;/pre&gt;Primary key column information is taken from &lt;i&gt;INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE&lt;/i&gt; view.&lt;pre class="brush: sql"&gt;&lt;br /&gt;SELECT QUOTENAME(COLUMN_NAME)&lt;br /&gt;FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE&lt;br /&gt;WHERE TABLE_NAME = @tableName AND TABLE_SCHEMA = @schemaName&lt;br /&gt;AND OBJECTPROPERTY(OBJECT_ID(QUOTENAME(CONSTRAINT_SCHEMA)&lt;br /&gt;         + '.' + QUOTENAME(CONSTRAINT_NAME))&lt;br /&gt;      ,'IsPrimaryKey') = 1&lt;br /&gt;&lt;/pre&gt;If no primary key was found an exception will be thrown. If the primary key consists of more than one column an exception will be thrown since this version of &lt;i&gt;SqlBinaryData&lt;/i&gt; class does not support composite primary keys.&lt;br/&gt;&lt;br/&gt;Binary column information is taken from &lt;i&gt;INFORMATION_SCHEMA.COLUMNS&lt;/i&gt; view.&lt;pre class="brush: sql;"&gt;&lt;br /&gt;SELECT QUOTENAME(COLUMN_NAME), DATA_TYPE, CHARACTER_MAXIMUM_LENGTH&lt;br /&gt;FROM INFORMATION_SCHEMA.COLUMNS&lt;br /&gt;WHERE TABLE_NAME = @tableName&lt;br /&gt;   AND TABLE_SCHEMA = @schemaName&lt;br /&gt;   AND COLUMN_NAME = @columnName&lt;br /&gt;&lt;/pre&gt;If the returned column is not of type VARBINARY(MAX) an exception will be thrown.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;SQL Injection&lt;/h3&gt;To avoid possibility of SQL injection all provided table and column names are quoted by utilizing the SQL Server &lt;a href="http://msdn.microsoft.com/en-us/library/ms176114.aspx"&gt;QUOTENAME&lt;/a&gt; function, as shown above. All values, like the value of the primary key to stream binary data from or to, are passed to SQL Server as &lt;i&gt;SqlParameter&lt;/i&gt; objects to avoid SQL injection and let SQL Server reuse cached execution plans.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;SqlBinaryReader Class&lt;/h3&gt;Internal class that is responsible for streaming read access to BLOB. As already noted, it implements a &lt;i&gt;System.IO.Stream&lt;/i&gt; to provide a well known standard behavior.&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;class SqlBinaryReader : Stream { //...&lt;br /&gt;&lt;/pre&gt;The most important public method the Read method, that copies data into a specified array:&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public override int Read(byte[] buffer, int offset, int count) {&lt;br /&gt;   // first read&lt;br /&gt;   if (_buffer == null)&lt;br /&gt;      ReadChunk();&lt;br /&gt;&lt;br /&gt;   int done = 0;&lt;br /&gt;&lt;br /&gt;   while (count != done) {&lt;br /&gt;      // read buffered data into provided buffer&lt;br /&gt;      done += ReadInternal(buffer, offset + done, count - done);&lt;br /&gt;      // end of DB data reached&lt;br /&gt;      if (_buffer.Length &amp;lt; _info.BufferSize)&lt;br /&gt;         break;&lt;br /&gt;      // read next chunk from database if needed&lt;br /&gt;      if (done &amp;lt; count)&lt;br /&gt;         ReadChunk();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return done;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The called method &lt;i&gt;ReadInternal&lt;/i&gt; gets data out of the internal buffer into the specified one. The &lt;i&gt;ReadChunk&lt;/i&gt; method handles the database access and is shown here:&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;private void ReadChunk() {&lt;br /&gt;   SqlBinaryMetaData metaData = GetMetaData();&lt;br /&gt;   // create an internal database connection if not yet available&lt;br /&gt;   if (_cn == null)&lt;br /&gt;      _cn = _info.CreateConnection(GetMetaData().ConnectionString);&lt;br /&gt;&lt;br /&gt;   // create an internal data reader&lt;br /&gt;   if (_reader == null) {&lt;br /&gt;      string sql =&lt;br /&gt;         string.Format("SELECT {0} FROM {1} WHERE {2} = @pk",&lt;br /&gt;                        metaData.BinaryColumn,&lt;br /&gt;                        metaData.QualifiedTableName,&lt;br /&gt;                        metaData.PkColumn);&lt;br /&gt;      using (var cmd = new SqlCommand(sql, _cn)) {&lt;br /&gt;         cmd.Parameters.Add(_info.CreatePkParam());&lt;br /&gt;         // open the reader with sequencial access behavior to enable &lt;br /&gt;         // streaming data from database&lt;br /&gt;         _reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);&lt;br /&gt;         _reader.Read();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   int read = (int)_reader.GetBytes(0, _position, _buffer, 0, _buffer.Length);&lt;br /&gt;   if (read != _buffer.Length)&lt;br /&gt;      Array.Resize(ref _buffer, read);&lt;br /&gt;   _offset = 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The internal instance of an &lt;i&gt;SqlDataReader&lt;/i&gt; is created with option &lt;i&gt;CommandBehavior.SequentialAccess&lt;/i&gt; what causes ADO.NET to stream data out of SQL Server instead of pulling all data in one chunk. The reader and its parent connection are cleared from memory when the stream instance becomes disposed.&lt;br/&gt;&lt;br/&gt;Data will always be streamed with the specified buffer size, even if the caller requests a larger count of bytes in one call. This is to avoid a too high memory utilization on server side. So it is still possible to get 10MB of data in one single call of &lt;i&gt;Read&lt;/i&gt; method, even if this might cause 10 database calls if buffer size is specified for 1MB.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;SqlBinaryWriter Class&lt;/h3&gt;Internal class that is responsible for streaming write access to a VARBINARY(MAX) column of a tables row. As well as the &lt;i&gt;SqlBinaryReader&lt;/i&gt; it implements a &lt;i&gt;System.IO.Stream&lt;/i&gt;.&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;class SqlBinaryWriter : Stream {&lt;br /&gt;&lt;/pre&gt;The two important public methods of the write stream are &lt;i&gt;Write&lt;/i&gt; and &lt;i&gt;Flush&lt;/i&gt; method.&lt;br/&gt;&lt;br/&gt;The &lt;i&gt;Write&lt;/i&gt; method streams the provided data in chunks into the internal buffer. Whenever the internal buffer is full, it calls the &lt;i&gt;Flush&lt;/i&gt; method which is responsible to writing the current chunk of data to the server.&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public override void Write(byte[] buffer, int offset, int count) {&lt;br /&gt;   if (_failedState)&lt;br /&gt;      throw new InvalidOperationException("Stream is in a failed state");&lt;br /&gt;&lt;br /&gt;   int done = 0;&lt;br /&gt;   while (done != count) {&lt;br /&gt;      int chunk = Math.Min(_internalBuffer.Length - _internalOffset, count - done);&lt;br /&gt;      // push a chunk of bytes into the internal buffer&lt;br /&gt;      Array.Copy(buffer, offset + done, _internalBuffer, _internalOffset, chunk);&lt;br /&gt;      _internalOffset += chunk;&lt;br /&gt;      // if internal buffer is full, flush to database&lt;br /&gt;      if (_internalOffset == _internalBuffer.Length)&lt;br /&gt;         Flush();&lt;br /&gt;      done += chunk;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;To avoid unneeded memory copying on server side new data are appended to the database field by using the &lt;i&gt;VARBINARY(MAX).WRITE&lt;/i&gt; method (see &lt;a href="http://msdn.microsoft.com/en-us/library/ms177523.aspx"&gt;UPDATE (Transact SQL)&lt;/a&gt;) which performs a partial update of existing data instead of a complete reallocation of all data.&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public override void Flush() {&lt;br /&gt;   if (_internalOffset == 0)&lt;br /&gt;      return;&lt;br /&gt;   if (_failedState)&lt;br /&gt;      return;&lt;br /&gt;&lt;br /&gt;   SqlBinaryMetaData metaData = GetMetaData();&lt;br /&gt;&lt;br /&gt;   using (SqlConnection cn = _info.CreateConnection(metaData.ConnectionString))&lt;br /&gt;   using (var tran = cn.BeginTransaction()) {&lt;br /&gt;      try {&lt;br /&gt;         // handle NULL value and "append" configuration&lt;br /&gt;         PrepareValue(cn, tran);&lt;br /&gt;         // UPDATE SchemaName.TableName &lt;br /&gt;         // SET BinaryColumn.WRITE(@buffer, @offset, @count) &lt;br /&gt;         // WHERE PkColumn = @pk&lt;br /&gt;         string sql =&lt;br /&gt;            string.Format("UPDATE {0} SET {1}.WRITE(@buffer, @offset, @count) WHERE {2} = @pk",&lt;br /&gt;                          metaData.QualifiedTableName,&lt;br /&gt;                          metaData.BinaryColumn,&lt;br /&gt;                          metaData.PkColumn);&lt;br /&gt;         using (var cmd = new SqlCommand(sql, cn)) {&lt;br /&gt;            cmd.Transaction = tran;&lt;br /&gt;&lt;br /&gt;            var bufferParam = cmd.Parameters.Add("@buffer", SqlDbType.VarBinary, _info.BufferSize);&lt;br /&gt;            var offsetParam = cmd.Parameters.Add("@offset", SqlDbType.Int);&lt;br /&gt;            var countParam = cmd.Parameters.Add("@count", SqlDbType.Int);&lt;br /&gt;            cmd.Parameters.Add(_info.CreatePkParam());&lt;br /&gt;&lt;br /&gt;            byte[] buffer;&lt;br /&gt;            if (_internalOffset == _internalBuffer.Length)&lt;br /&gt;               buffer = _internalBuffer;&lt;br /&gt;            else {&lt;br /&gt;               // avoid bumping not needed data over network&lt;br /&gt;               buffer = new byte[_internalOffset];&lt;br /&gt;               Array.Copy(_internalBuffer, buffer, _internalOffset);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            bufferParam.Value = buffer;&lt;br /&gt;            // VARBINARY(MAX).WRITE works with a zero based index&lt;br /&gt;            offsetParam.Value = _position;&lt;br /&gt;            countParam.Value = _internalOffset;&lt;br /&gt;            // write chunk&lt;br /&gt;            int affected = cmd.ExecuteNonQuery();&lt;br /&gt;            _info.AssertOneRowAffected(affected);&lt;br /&gt;            _position += _internalOffset;&lt;br /&gt;            _internalOffset = 0;&lt;br /&gt;         }&lt;br /&gt;         tran.Commit();&lt;br /&gt;      }&lt;br /&gt;      catch {&lt;br /&gt;         _failedState = true;&lt;br /&gt;         tran.Rollback();&lt;br /&gt;         throw;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The &lt;i&gt;PrepareValue&lt;/i&gt; method, called from &lt;i&gt;Flush&lt;/i&gt; handles the preparation of the database field for the first call. If the stream was created with option "append" false it resets any existing data to initial value "0x". If the stream was created with "append" true it determines the current length of the data in the binary field or sets it to "0x", if its value is currently NULL.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;How To Use&lt;/h3&gt;Here is an example that shows how to use the class to streaming write and read data.&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;SqlBinaryData data = &lt;br /&gt;   SqlBinaryData.CreateLongPrimaryKey(ConnectionString, "TestBlob", "Data", 3L, 5);&lt;br /&gt;&lt;br /&gt;byte[] expected = Guid.NewGuid().ToByteArray();&lt;br /&gt;using (var writer = data.OpenWrite(false)) {&lt;br /&gt;   writer.Write(expected, 0, 4);&lt;br /&gt;   writer.Write(expected, 4, expected.Length - 4);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;byte[] actual = new byte[expected.Length];&lt;br /&gt;using (var reader = data.OpenRead()) {&lt;br /&gt;   reader.Read(actual, 0, 3);&lt;br /&gt;   reader.Read(actual, 3, actual.Length - 3);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Assert.IsTrue(expected.SequenceEqual(actual));&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;To create a new instance of a streaming providing &lt;i&gt;SqlBinaryData&lt;/i&gt; class you can use the constructor. The parameter &lt;i&gt;pkParam&lt;/i&gt; is used as specification of the primary key column.&lt;pre class="brush: csharp"&gt;&lt;br /&gt;public SqlBinaryData(string connectionString, string tableName, string tableSchema,&lt;br /&gt;                     string binaryColumn, SqlParameter pkParam, object pkValue, &lt;br /&gt;                     int bufferSize);&lt;br /&gt;&lt;/pre&gt;In case of an INT, BIGINT or UNIQUEIDENTIFIER primary key column, you can also use one of the static factory methods of &lt;i&gt;SqlBinaryData&lt;/i&gt; (each one with and without specifying a table schema name):&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public static SqlBinaryData CreateIntPrimaryKey(string connectionString, &lt;br /&gt;      string tableName, string tableSchema, string binaryColumn, int pkValue, int bufferSize);&lt;br /&gt;&lt;br /&gt;public static SqlBinaryData CreateIntPrimaryKey(string connectionString, &lt;br /&gt;      string tableName, string binaryColumn, int pkValue, int bufferSize);&lt;br /&gt;&lt;br /&gt;public static SqlBinaryData CreateLongPrimaryKey(string connectionString, &lt;br /&gt;      string tableName, string tableSchema, string binaryColumn, long pkValue, int bufferSize);&lt;br /&gt;&lt;br /&gt;public static SqlBinaryData CreateLongPrimaryKey(string connectionString, &lt;br /&gt;      string tableName, string binaryColumn, long pkValue, int bufferSize);&lt;br /&gt;&lt;br /&gt;public static SqlBinaryData CreateGuidPrimaryKey(string connectionString, &lt;br /&gt;      string tableName, string binaryColumn, Guid pkValue, int bufferSize);&lt;br /&gt;&lt;br /&gt;public static SqlBinaryData CreateGuidPrimaryKey(string connectionString, &lt;br /&gt;      string tableName, string tableSchema, string binaryColumn, Guid pkValue, int bufferSize);&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;&lt;h3&gt;Transactions&lt;/h3&gt;Since the classes create their database connections inside of the class you cannot directly use a &lt;i&gt;SqlTransaction&lt;/i&gt; to scope your DML operations. However, since the ADO.NET data provider for SQL Server supports transaction scoping it is still possible to ensure an isolated processing by using the &lt;a href="http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx"&gt;System.Transactions.TransactionScope&lt;/a&gt;.&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;using (TransactionScope tran = new TransactionScope()) {&lt;br /&gt;   using (var cn = CreateConnection()) {&lt;br /&gt;      // do stuff&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   var binaryData = CreateBinary(10L, 16);&lt;br /&gt;   using (var stream = binaryData.OpenWrite(false)) {&lt;br /&gt;      byte[] toWrite = Guid.NewGuid().ToByteArray();&lt;br /&gt;      stream.Write(toWrite, 0, toWrite.Length);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   using (var cn = CreateConnection()) {&lt;br /&gt;      // do more stuff&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;&lt;h3&gt;Server Side Resource Allocation&lt;/h3&gt;Since we can specify the exact buffer size to work with and chunks are always taken in this size we know that we are fine on client side. The other side to look at is what resources are allocated on server side. We will do this by imitating the classes behavior in SQL Server Management studio and checking results in SQL Server Profiler.&lt;br/&gt;&lt;br/&gt;Here is the setup up for the following tests.&lt;br/&gt;&lt;pre class="brush: sql"&gt;&lt;br /&gt;SET NOCOUNT ON;&lt;br /&gt;&lt;br /&gt;IF (OBJECT_ID('TestBlob') IS NOT NULL)&lt;br /&gt;   DROP TABLE TestBlob;&lt;br /&gt;&lt;br /&gt;CREATE TABLE TestBlob (&lt;br /&gt;   Id INT NOT NULL PRIMARY KEY CLUSTERED&lt;br /&gt;   ,Data VARBINARY(MAX)&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;INSERT INTO TestBlob VALUES (1, 0x);&lt;br /&gt;INSERT INTO TestBlob VALUES (2, 0x);&lt;br /&gt;GO&lt;br /&gt;&lt;/pre&gt;First, let's UPDATE a row, with 50MB of binary data in one single batch.&lt;br/&gt;&lt;pre class="brush: sql"&gt;&lt;br /&gt;-- one big update with 50MB of data&lt;br /&gt;DECLARE @data VARBINARY(MAX) = &lt;br /&gt;   CONVERT(VARBINARY(MAX), REPLICATE(CONVERT(VARBINARY(MAX), NEWID()), 65536 * 50));&lt;br /&gt;&lt;br /&gt;UPDATE TestBlob SET Data = @data WHERE Id = 1;&lt;br /&gt;&lt;/pre&gt;A look into SQL Server Profiler shows, as expected, a huge resource allocation.&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/SqlBinaryData_SingleUpdate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://sites.google.com/site/florianreischl/blogspot-files/SqlBinaryData_SingleUpdate.png"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;br/&gt;Now, let's get the same amount of data into SQL Server by using the WRITE method and sending in 10 chunks of 5MB. To keep the test valid we have to remember the current position to write at. To keep this information available over the scope of a batch we can use the the &lt;a href="http://msdn.microsoft.com/en-us/library/ms180125.aspx"&gt;CONTEXT_INFO()&lt;/a&gt; which allows to store up to 128 bytes of custom information for the current session.&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: sql"&gt;&lt;br /&gt;SET CONTEXT_INFO 0x; -- clear the context&lt;br /&gt;GO&lt;br /&gt;-- 10 updates, each with 5MB&lt;br /&gt;DECLARE @offset INT = &lt;br /&gt;   ISNULL(CONVERT(INT, SUBSTRING(CONTEXT_INFO(), 1, 4)), 0);&lt;br /&gt;--PRINT @offset;&lt;br /&gt;DECLARE @data VARBINARY(MAX) = &lt;br /&gt;   CONVERT(VARBINARY(MAX), REPLICATE(CONVERT(VARBINARY(MAX), NEWID()), 65536 * 5));&lt;br /&gt;DECLARE @data_length INT = DATALENGTH(@data)&lt;br /&gt;&lt;br /&gt;UPDATE TestBlob SET Data.WRITE(@data, @offset, @data_length) WHERE Id = 2;&lt;br /&gt;SET @offset += @data_length;&lt;br /&gt;&lt;br /&gt;SET CONTEXT_INFO @offset;&lt;br /&gt;GO 10 -- count of batch execution loops&lt;br /&gt;&lt;/pre&gt;Another look into Profiler shows, we get 10 statements with a really nice resource allocation.&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/SqlBinaryData_MultipleUpdates.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://sites.google.com/site/florianreischl/blogspot-files/SqlBinaryData_MultipleUpdates.png"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;br/&gt;Unfortunately I cannot provide a valid test result for read operations using the &lt;i&gt;SqlDataReader.GetBytes&lt;/i&gt; method at the moment. This is caused by an issue of SQL Server Profiler when trying to trace BLOB data (see MS Connect &lt;a href="https://connect.microsoft.com/SQLServer/feedback/details/304225/msft-edw-profiler-displays-trace-skipped-records-for-large-530kb-batch"&gt;MSFT:EDW - Profiler displays "Trace Skipped Records" for large (&gt;530Kb) batch&lt;/a&gt;). I don't want to show test results with too small binary data since measuring inaccuracy might be too high. If you can tell me a way of how to get valid test results for this I would be happy if you let me know.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Restrictions&lt;/h3&gt;The current version of this class supports only single column primary keys. An exception will be thrown if a primary key consists of more than one column. Let me know, if there is a need of a version that supports composite primary keys.&lt;br/&gt;&lt;br/&gt;It is required that the table containing the binary data has a primary key, the class doesn't work with heap tables. An exception is thrown if an accessed table does not have a primary key.&lt;br/&gt;&lt;br/&gt;The class supports only columns from type VARBINARY(MAX). If there is a need for a VARCHAR(MAX)/NVARCHAR(MAX) based version, let me know.&lt;br/&gt;&lt;br/&gt;The class does not handle any possible concurrent client sessions to avoid unwanted database locks. If data, accessed by a current instance of a read or write stream become modified by another user, the processed data will become most likely corrupted on client or even server side. To secure write operations use a &lt;i&gt;TransactionScope&lt;/i&gt; surrounding the writing stream.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;IBinaryData Interface&lt;/h3&gt;The &lt;i&gt;SqlBinaryData&lt;/i&gt; class implements an interface called &lt;i&gt;IBinaryData&lt;/i&gt;. This interface is not required for using this class, but I use it for unit testing purposes in business layers of a project where it allows me to work with files of a directory instead of data from a database. Feel free to remove it.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Attachments&lt;/h3&gt;Here you can find ZIP archive containing all classes of &lt;i&gt;SqlBinaryData&lt;/i&gt; and a NUnit based test class.&lt;ul&gt;&lt;li&gt;The sources &lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/SqlBinaryData.zip"&gt;SqlBinaryData.zip&lt;/a&gt;&lt;/li&gt;&lt;li&gt;The unit tests &lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/SqlBinaryDataTest.cs"&gt;SqlBinaryDataTest.cs&lt;/a&gt;&lt;/li&gt;&lt;li&gt;The SQL script to do the server side memory allocation tests &lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/SqlBinaryData_DbResourceAllocationTest.sql"&gt;SqlBinaryData_DbResourceAllocationTest.sql&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-6777418522230911370?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/6777418522230911370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2011/08/streaming-sql-server-varbinarymax-in.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/6777418522230911370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/6777418522230911370'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2011/08/streaming-sql-server-varbinarymax-in.html' title='Streaming SQL Server VARBINARY(MAX) In Chunks With ADO.NET'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-4101863629979381492</id><published>2011-08-16T07:16:00.000-07:00</published><updated>2011-08-16T07:17:12.078-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server'/><category scheme='http://www.blogger.com/atom/ns#' term='ado.net'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>ADO.NET Connection Pooling, Internals and Issues</title><content type='html'>&lt;h3&gt;Description&lt;/h3&gt;The creation of a new database connection is a relatively expensive process on server side. The server needs to allocate new memory, create a new session, allocate all needed client information, authenticate the client and so on. On the other side, it does not make sense to keep keep connections open for the whole lifetime of a application, since this causes a higher session management overhead on server side due to many concurrent connections.&lt;br /&gt;&lt;br /&gt;To handle those two issues, ADO.NET uses connection pooling. This means, the well known &lt;i&gt;SqlConnection&lt;/i&gt; object from .NET framework is just a wrapper for the real, internal database connection. Whenever a new &lt;i&gt;SqlConnection&lt;/i&gt; becomes opened it asks the connection pool for an existing, and currently not used, internal connection. If an existing, free connection is available ADO.NET wont create a new database connection but reuse the existing one. As soon as the connection is not needed any more it becomes sent back into the connection pool. If a connection is not used for a longer time it becomes automatically closed by the ADO.NET connection pooler, to release resources on SQL Server. To determine if an internal connection can be used for a current request by a &lt;i&gt;SqlConnection&lt;/i&gt;, ADO.NET compares several (not all) connection string information. This includes authentication information, database name, transaction context enlisting configuration and so forth.&lt;br /&gt;&lt;br /&gt;This blog post focuses on ADO.NET SqlClient and SQL Server. Some of the information might be different when working with other database servers or other data providers.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Myth Close and Dispose&lt;/h3&gt;Many books and web resources preach that it is important to always &lt;i&gt;Close&lt;/i&gt; &lt;b&gt;and&lt;/b&gt; dispose a connection, to ensure that the internal connection will be sent back to the connection pool. Until .NET 3.5 even MSDN stated this, but this became fixed version 4.0. Both ways, calling the &lt;i&gt;Close&lt;/i&gt; method &lt;b&gt;or&lt;/b&gt; by disposing the &lt;i&gt;SqlConnection&lt;/i&gt; will actually send the connection back to the pool. Since the using-directive provides a language integrated way to dispose a component as soon as it goes out of scope, I usually prefer this over calling the &lt;i&gt;Close&lt;/i&gt; method in a try-catch-&lt;b&gt;finally&lt;/b&gt; block.&lt;br /&gt;&lt;br /&gt;Here's a little sample that shows that both ways cause a correct connection pooling:&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;string cnStr = "server=(local);database=Sandbox;trusted_connection=sspi;";&lt;br /&gt;string sql = "SELECT connect_time FROM sys.dm_exec_connections WHERE session_id = @@SPID";&lt;br /&gt;SqlConnection cn1 = new SqlConnection(cnStr);&lt;br /&gt;&lt;br /&gt;// close the connection but don't dispose it&lt;br /&gt;cn1.Open();&lt;br /&gt;using (SqlCommand cmd = new SqlCommand(sql, cn1)) {&lt;br /&gt;   DateTime loginTime = (DateTime)cmd.ExecuteScalar();&lt;br /&gt;   Console.WriteLine("New connection: {0}", loginTime.ToString("HH:mm:ss.fff"));&lt;br /&gt;}&lt;br /&gt;cn1.Close();&lt;br /&gt;&lt;br /&gt;// dispose but no close&lt;br /&gt;Thread.Sleep(500);&lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr)) {&lt;br /&gt;   cn.Open();&lt;br /&gt;   using (SqlCommand cmd = new SqlCommand(sql, cn)) {&lt;br /&gt;      DateTime loginTime = (DateTime)cmd.ExecuteScalar();&lt;br /&gt;      Console.WriteLine("After Close only: {0}", loginTime.ToString("HH:mm:ss.fff"));&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// result afer dispose but no close&lt;br /&gt;Thread.Sleep(500);&lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr)) {&lt;br /&gt;   cn.Open();&lt;br /&gt;   using (SqlCommand cmd = new SqlCommand(sql, cn)) {&lt;br /&gt;      DateTime loginTime = (DateTime)cmd.ExecuteScalar();&lt;br /&gt;      Console.WriteLine("After disposing only: {0}", loginTime.ToString("HH:mm:ss.fff"));&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;cn1.Dispose();&lt;br /&gt;Console.ReadLine();&lt;br /&gt;&lt;/pre&gt;By returning the &lt;i&gt;connect_time&lt;/i&gt; column from &lt;i&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms181509.aspx"&gt;sys.dm_exec_connections&lt;/a&gt;&lt;/i&gt; for our current session id we retrieve the creation time of the connection from SQL Server.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-gpeby3ikM38/TkWOe0-mTtI/AAAAAAAAAH4/hIiN9mXw180/s1600/ConnectionPooling1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-gpeby3ikM38/TkWOe0-mTtI/AAAAAAAAAH4/hIiN9mXw180/s1600/ConnectionPooling1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;As we see, in all cases we reuse the same, internal connection to SQL Server.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;How a Pooled Connection becomes Reset&lt;/h3&gt;Since ADO.NET does not know what happened in a previous session of a pooled connection, when it is returned to a new instance of a &lt;i&gt;SqlConnection&lt;/i&gt;, it has to reset the connection before it can be safely reused for another session. When resetting a connection all created temporary objects become dropped, all previously allocated resources are freed and the initially connected database will be set - if it was changed in the previous session. This resetting is done by calling the SQL Server procedure &lt;i&gt;sp_reset_connection&lt;/i&gt;.&lt;br/&gt;&lt;br/&gt;This alludes some issues. The ADO.NET connection pooler does &lt;b&gt;not reset&lt;/b&gt; the connection &lt;b&gt;when&lt;/b&gt; it is &lt;b&gt;sent back&lt;/b&gt; to the pool, &lt;b&gt;but when&lt;/b&gt; it is &lt;b&gt;returned&lt;/b&gt; to a new opening &lt;i&gt;SqlConnection&lt;/i&gt;, as shown in the next topics.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Temporary Tables and Named Constraints&lt;/h3&gt;When working with temporary tables in SQL Server, there is still an issue, names of temporary tables only need to be unique within the current connection, but names of constraints need to be unique for all current connections. Since SQL Server 2005 and following versions it is possible to define constraints without specifying a name for them. Previous versions did not support this feature and the syntax to specify a name for a table constraint is, for sure, still valid. When executing the following SQL statement in two concurrent connections you get an error message:&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;CREATE TABLE #t1 (&lt;br /&gt;   Id INT NOT NULL CONSTRAINT PK_TEMP PRIMARY KEY CLUSTERED&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;Only the first connection is able to create the temp table, the second connection gets the following error:&lt;br/&gt;&lt;pre style="color: red;"&gt;Msg 2714, Level 16, State 5, Line 1&lt;br /&gt;There is already an object named 'PK_TEMP' in the database.&lt;br /&gt;Msg 1750, Level 16, State 0, Line 1&lt;br /&gt;Could not create constraint. See previous errors.&lt;/pre&gt;&lt;br/&gt;This also affects ADO.NET connection pooling. Say, we've got two different processes, the first creates a new entry in a database and the second one listens for those entries to process them. When the first process finishes its work without an explicit &lt;i&gt;DROP&lt;/i&gt; of the temporary table, the connection stays open and the temporary table will stay in database until the connection is reused. If the second process tries to create the same temporary table it will receive the same exception.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Global Temporary Tables&lt;/h3&gt;Same problem as described for constraints of usual temporary tables applies to global temporary tables. Their name needs to be unique over all concurrent SQL Server connections. If one process creates a global temp table and does not explicitly drop it, when closing/disposing the SqlConnection, the table will stay on the server until the current process opens another connection to this server (and database). This behavior can cause confusing errors in a production system.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Release of Temporary Allocated Data&lt;/h3&gt;For sure, since temporary tables stay available until a connection becomes reused, this also implies that all data, stored in those tables, stay allocated until the process exists or reuses the connection.&lt;br/&gt;&lt;br/&gt;If we have a process that creates a temporary table and fills it with hundreds of thousands of rows those data will stay in &lt;i&gt;tempdb&lt;/i&gt; for probably longer than expected.&lt;br/&gt;&lt;br/&gt;One way to ensure all allocated resources and temp tables become cleaned as soon as the connection is closed would be to deactivate connection pooling. However, we should always try to avoid this. The cleanest way to avoid all previously described issues is to always, explicitly drop temporary objects.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Pooled Connection became Invalid&lt;/h3&gt;If an connection becomes invalid while it is in the connection pool, it will still be returned for next usage. This could be caused by network problems, a restart of the SQL Server service, a manual KILL of the connection on database side or several other reasons.&lt;br/&gt;&lt;br/&gt;Here is a little example that can be debugged to show this:&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;string cnStr = "server=(local);database=Sandbox;trusted_connection=sspi;";&lt;br /&gt;         &lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr))&lt;br /&gt;using (SqlCommand cmd = new SqlCommand("SELECT @@SPID", cn)) {&lt;br /&gt;   cn.Open();&lt;br /&gt;   Debug.Print("SPID: {0}", cmd.ExecuteScalar());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// at this point, restart the service or KILL the connection on server side&lt;br /&gt;&lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr))&lt;br /&gt;using (SqlCommand cmd = new SqlCommand("SELECT @@SPID", cn)) {&lt;br /&gt;   cn.Open();&lt;br /&gt;   Debug.Print("SPID: {0}", cmd.ExecuteScalar());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;When debugging this code and restarting the SQL Server service after the first connection became disposed and before the second connection becomes opened you will get an exception. In my case (since I'm working with a local instance of SQL Server):&lt;pre style="color: red;"&gt;&lt;br /&gt;A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)&lt;br /&gt;&lt;/pre&gt;At the time of this post, there is no built-in support of ADO.NET for SQL Server that tells the resource pool to verify the connection before it is returned to the &lt;i&gt;SqlConnection&lt;/i&gt;. However, if occasional network issues or other problems, that cause an invalid internal connection, sometimes happen in your environment, you can implement your custom connection validation in a factory method that creates your connections.&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;string cnStr = "server=(local);database=Sandbox;trusted_connection=sspi;";&lt;br /&gt;SqlConnection cn = new SqlConnection(cnStr);&lt;br /&gt;cn.Open();&lt;br /&gt;&lt;br /&gt;try {&lt;br /&gt;   using (SqlCommand cmd = new SqlCommand("DECLARE @i INT", cn)) {&lt;br /&gt;      cmd.ExecuteNonQuery();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;catch (SqlException ex) {&lt;br /&gt;   if (ex.Message.StartsWith("A transport-level error has occurred ")) {&lt;br /&gt;      cn = new SqlConnection(cnStr);&lt;br /&gt;      cn.Open();&lt;br /&gt;   }&lt;br /&gt;   else&lt;br /&gt;      throw;&lt;br /&gt;}&lt;br /&gt;return cn;&lt;br /&gt;&lt;/pre&gt;As you see, the connection sends a tiny SQL statement to the server before it is returned to the caller. If a transport-level exception occurs, the internal connection becomes removed from pool and another new connection will be created and returned. You can replace the "DECLARE @i INT;" SQL statement with an empty stored procedure called &lt;i&gt;usp_VerifyConnection&lt;/i&gt;. This might be slightly faster (not tested, though), but will definitely look less confusing in SQL Server traces ;-).&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Control the Connection Pool over Connection String&lt;/h3&gt;The &lt;i&gt;SqlConnection.ConnectionString&lt;/i&gt; provides several attributes that allow to control the behavior of ADO.NET pooling.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Connection Lifetime&lt;/b&gt; can be used to specify a maximum life time for a connection in seconds. When a connection is returned to the pool this value will be compared to the (client side) creation time of the connection. If the connections lifetime is timed out, it will be closed and not put into pool. Attention, this implies if a connection with connection is sent back into the pool before its lifetime elapsed and not used for a long time, &lt;b&gt;it will still stay opened and reused&lt;/b&gt; for one more time!&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;// connection string with a lifetime of 10 seconds&lt;br /&gt;string cnStr = "server=(local);database=Sandbox;trusted_connection=sspi;connection lifetime=10";&lt;br /&gt;string sql = "SELECT connect_time FROM sys.dm_exec_connections WHERE session_id = @@SPID";&lt;br /&gt;&lt;br /&gt;// create a new connection with 10 seconds lifetime and send it back to the pool&lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr))&lt;br /&gt;using (SqlCommand cmd = new SqlCommand(sql, cn)) {&lt;br /&gt;   cn.Open();&lt;br /&gt;   DateTime connectTime = (DateTime)cmd.ExecuteScalar();&lt;br /&gt;   Debug.Print("Connect time: {0}", connectTime.ToString("HH:mm:ss.fff"));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// wait 15 seconds&lt;br /&gt;Thread.Sleep(15000);&lt;br /&gt;// aquire a new connection and release it&lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr))&lt;br /&gt;using (SqlCommand cmd = new SqlCommand(sql, cn)) {&lt;br /&gt;   cn.Open();&lt;br /&gt;   DateTime connectTime = (DateTime)cmd.ExecuteScalar();&lt;br /&gt;   Debug.Print("Connect time: {0}", connectTime.ToString("HH:mm:ss.fff"));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// create another connection&lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr))&lt;br /&gt;using (SqlCommand cmd = new SqlCommand(sql, cn)) {&lt;br /&gt;   cn.Open();&lt;br /&gt;   DateTime connectTime = (DateTime)cmd.ExecuteScalar();&lt;br /&gt;   Debug.Print("Connect time: {0}", connectTime.ToString("HH:mm:ss.fff"));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;And here the output of this test:&lt;pre&gt;&lt;br /&gt;Connect time: 12:47:07.617&lt;br /&gt;Connect time: 12:47:07.617&lt;br /&gt;Connect time: 12:47:22.837&lt;br /&gt;&lt;/pre&gt;As we see, even if the specified connection lifetime is elapsed, the second connection will get the pooled connection. As long as the elapsed connection is not sent back to the pool it will stay active. Only the third connection retrieves a new created connection, since the connections lifetime was already elapsed as it was sent to the pool.&lt;/br&gt;&lt;br/&gt;The default value for Connection Lifetime is zero, what means a maximum lifetime.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Min Pool Size&lt;/b&gt; and &lt;b/&gt;Max Pool Size&lt;/b&gt; can be used to specify a minimum/maximum count of pooled connections. The default value for Min Pool Size is zero, the default value of Max Pool Size is 100. When trying to use more concurrent connections than specified value of Max Pool Size you will get an exception.&lt;br/&gt;&lt;br/&gt;The &lt;b&gt;Pooling&lt;/b&gt; attribute (default 'true') says if connection pooling shall be used for the created connection or not. If you use a &lt;i&gt;SqlConnection&lt;/i&gt; with pooling 'false' the database connection will always be newly created and closed after using it.&lt;br/&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;// connection string with "pooling=false"&lt;br /&gt;string cnStr = "server=(local);database=Sandbox;trusted_connection=sspi;pooling=false";&lt;br /&gt;string sql = "SELECT connect_time FROM sys.dm_exec_connections WHERE session_id = @@SPID";&lt;br /&gt;&lt;br /&gt;// create a new connection and print the current session id&lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr))&lt;br /&gt;using (SqlCommand cmd = new SqlCommand(sql, cn)) {&lt;br /&gt;   cn.Open();&lt;br /&gt;   DateTime connectTime = (DateTime)cmd.ExecuteScalar();&lt;br /&gt;   Debug.Print("Connect time: {0}", connectTime.ToString("HH:mm:ss.fff"));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// create a new connection and print the current session id&lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr))&lt;br /&gt;using (SqlCommand cmd = new SqlCommand(sql, cn)) {&lt;br /&gt;   cn.Open();&lt;br /&gt;   DateTime connectTime = (DateTime)cmd.ExecuteScalar();&lt;br /&gt;   Debug.Print("Connect time: {0}", connectTime.ToString("HH:mm:ss.fff"));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;And here is the output:&lt;br/&gt;&lt;pre&gt;&lt;br /&gt;Connect time: 13:41:32.790&lt;br /&gt;Connect time: 13:41:33.050&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;As we see, the connect time on server side is different for both connections where it would be equal if we would have reused the same internal connection for the second &lt;i&gt;SqlConnection&lt;/i&gt;.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Enlist&lt;/b&gt; (default 'true') attribute is a more special than the other connection pooling related attributes of connection string. If you don't work with distributed systems and/or &lt;i&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.transactions.aspx"&gt;Systems.Transactions&lt;/a&gt; &lt;/i&gt; namespace, you wont need this attribute. The Enlist attribute is important if you need to control how to span transactions over more than one transactional sub-system (like database servers, WCF services, ...). If Enlist is set to 'true' and a parent transaction context is available for the static property &lt;i&gt;System.Transactions.Transaction.Current&lt;/i&gt;, ADO.NET will automatically register the SQL connection and its transaction in this transaction context. If you commit your database transaction (implicit or explicit) the transaction will stay pending until the parent transaction becomes committed or rolled back. Today, the most common way to manage those parent transactions is utilizing the &lt;i&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx"&gt;TransactionScope&lt;/a&gt;&lt;/i&gt; class.&lt;br/&gt;&lt;br/&gt;A hypothetical system, that might use transaction scopes, is a order management system that automatically creates a shipping order by utilizing a suppliers web-service when an order becomes created or approved. Here we need to update/create new data in a local database and create a shipping order over a web-service within one transaction. If both systems support (and allow) transactions a transaction scope can be used to ensure that all data are either written or not.&lt;br/&gt;&lt;br/&gt;If Enlist is set to 'false', a new connection will not be enlisted to an existing transaction scope and behave like no transaction scope was available. All database transactions become committed, independent if the parent transaction will fail or succeed.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Control the Connection Pool over static SqlConnection methods&lt;/h3&gt;In addition to the control mechanisms provided by the connection string, ADO.NET &lt;i&gt;SqlConnection&lt;/i&gt; provides two static methods to partially, or completely clear the current pool.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;SqlConnection.ClearPool(SqlConnection)&lt;/b&gt; clears all pooled connections that match the provided connection - by its connection string.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;SqlConnection.ClearAllPools&lt;/b&gt; clears all currently pooled SQL Server connections.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Pool Fragmentation&lt;/h3&gt;There are two more possible issues with ADO.NET connection pooling. Though, I find both are well described at &lt;a href="http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx"&gt;SQL Server Connection Pooling (ADO.NET)&lt;/a&gt;, so I just quote the paragraphs for sake of completeness.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Pool Fragmentation Due to Integrated Security (Windows Authentication)&lt;/b&gt;&lt;blockquote&gt;Connections are pooled according to the connection string plus the user identity. Therefore, if you use Basic authentication or Windows Authentication on the Web site and an integrated security login, you get one pool per user. Although this improves the performance of subsequent database requests for a single user, that user cannot take advantage of connections made by other users. It also results in at least one connection per user to the database server. This is a side effect of a particular Web application architecture that developers must weigh against security and auditing requirements.&lt;/blockquote&gt;&lt;b&gt;Pool Fragmentation Due to Many Databases&lt;/b&gt;&lt;blockquote&gt;Many Internet service providers host several Web sites on a single server. They may use a single database to confirm a Forms authentication login and then open a connection to a specific database for that user or group of users. The connection to the authentication database is pooled and used by everyone. However, there is a separate pool of connections to each database, which increase the number of connections to the server.&lt;br/&gt;&lt;br/&gt;This is also a side-effect of the application design. There is a relatively simple way to avoid this side effect without compromising security when you connect to SQL Server. Instead of connecting to a separate database for each user or group, connect to the same database on the server and then execute the Transact-SQL USE statement to change to the desired database. The following code fragment demonstrates creating an initial connection to the master database and then switching to the desired database specified in the databaseName string variable.&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;// Assumes that command is a SqlCommand object and that&lt;br /&gt;// connectionString connects to master.&lt;br /&gt;command.Text = "USE DatabaseName";&lt;br /&gt;using (SqlConnection connection = new SqlConnection(&lt;br /&gt;  connectionString))&lt;br /&gt;  {&lt;br /&gt;    connection.Open();&lt;br /&gt;    command.ExecuteNonQuery();&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Two short things to the second quote. I would not restrict this possible issue to web applications. This kind of pool fragmentation can also happen on application servers that work with many databases on same database server. I don't know why MSDN suggests to use a explicit &lt;i&gt;SqlCommand&lt;/i&gt; to change the database, instead of using the &lt;i&gt;SqlConnection.ChangeDatabase&lt;/i&gt; instance method.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Sources&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx"&gt;MSDN: SQL Server Connection Pooling (ADO.NET)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring.aspx"&gt;MSDN: SqlConnection.ConnectionString Property&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.codeproject.com/KB/dotnet/ADONET_ConnectionPooling.aspx"&gt;Code Project: ADO.NET Connection Pooling at a Glance&lt;/a&gt;&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/6936017315111598402-4101863629979381492?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/4101863629979381492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2011/08/adonet-connection-pooling-internals-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/4101863629979381492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/4101863629979381492'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2011/08/adonet-connection-pooling-internals-and.html' title='ADO.NET Connection Pooling, Internals and Issues'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-gpeby3ikM38/TkWOe0-mTtI/AAAAAAAAAH4/hIiN9mXw180/s72-c/ConnectionPooling1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-4359614311023899351</id><published>2011-08-10T03:05:00.000-07:00</published><updated>2011-08-10T03:05:10.200-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><category scheme='http://www.blogger.com/atom/ns#' term='threading'/><title type='text'>Generic C# Resource Pool</title><content type='html'>I guess this becomes another &lt;i&gt;almost&lt;/i&gt; code-only blog.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Definition&lt;/h3&gt;A resource pool is a class that manages a synchronized access of (theoretically) infinite callers of a restricted count of resource items.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-fW2xw_BTsW0/TkJP5n0lgLI/AAAAAAAAAH0/G1uFQBNddU8/s1600/ResourcePool.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-fW2xw_BTsW0/TkJP5n0lgLI/AAAAAAAAAH0/G1uFQBNddU8/s1600/ResourcePool.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;One reason to use a resource pool could be a integrated sub system that is restricted by its maximum count of concurrent accessing threads. This could be a web service with a restricted count of sessions. Another reason for a resource pool is a resource that becomes working slow when it becomes accessed by to many concurrent connections. This could be a web-service, a database or a farm of processing servers. A third reason for a resource pool could be a resource that takes long to become initialized, but can be reused. This could be database connections, XSLT transformation classes, custom XML serializers or many other classes.&lt;br /&gt;Some well known .NET framework implementations of resource pools are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The ADO.NET connection pooling mechanism&lt;/li&gt;&lt;li&gt;The &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx"&gt;System.Reflection.TheadPool&lt;/a&gt; class&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;h3&gt;Implementation&lt;/h3&gt;A few month ago I wrote myself a generic resource pool class that helps me to get those kinds of bottle necks managed.&lt;br /&gt;&lt;br/&gt;Here is my implementation of a generic, thread safe C# resource pool. All source code files, as well as some NUnit tests, are also attached as downloadable files at bottom of this post.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;// ===================================================================&lt;br /&gt;// PoolItem&amp;lt;T&amp;gt;&lt;br /&gt;// ===================================================================&lt;br /&gt;&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Represents an item in the &amp;lt;see cref="ResourcePool{T}"/&amp;gt;&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;typeparam name="T"&amp;gt;The type of the resource to be hold&amp;lt;/typeparam&amp;gt;&lt;br /&gt;public sealed class PoolItem&amp;lt;T&amp;gt; : IDisposable where T : class {&lt;br /&gt;   internal PoolItem(ResourcePool&amp;lt;T&amp;gt; pool, T resource) {&lt;br /&gt;      _pool = pool;&lt;br /&gt;      _resource = resource;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private T _resource;&lt;br /&gt;   private readonly ResourcePool&amp;lt;T&amp;gt; _pool;&lt;br /&gt;&lt;br /&gt;   public static implicit operator T(PoolItem&amp;lt;T&amp;gt; item) {&lt;br /&gt;      return item.Resource;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Gets the resource hold by this resource pool item&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   public T Resource { get { return _resource; } }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Disposes this instance of an resource pool item and sends the resource back&lt;br /&gt;   /// to the pool&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   public void Dispose() {&lt;br /&gt;      _pool.SendBackToPool(_resource);&lt;br /&gt;      _resource = null;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// ===================================================================&lt;br /&gt;// ResourcePool&amp;lt;T&amp;gt;&lt;br /&gt;// ===================================================================&lt;br /&gt;&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Generic pool class&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;typeparam name="T"&amp;gt;The type of items to be stored in the pool&amp;lt;/typeparam&amp;gt;&lt;br /&gt;public class ResourcePool&amp;lt;T&amp;gt; : IDisposable where T : class {&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Creates a new pool&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="factory"&amp;gt;The factory method to create new items to&lt;br /&gt;   ///  be stored in the pool&amp;lt;/param&amp;gt;&lt;br /&gt;   public ResourcePool(Func&amp;lt;ResourcePool&amp;lt;T&amp;gt;, T&amp;gt; factory) {&lt;br /&gt;      if (factory == null)&lt;br /&gt;         throw new ArgumentNullException("factory");&lt;br /&gt;      _factoryMethod = factory;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private readonly Func&amp;lt;ResourcePool&amp;lt;T&amp;gt;, T&amp;gt; _factoryMethod;&lt;br /&gt;   private ConcurrentQueue&amp;lt;PoolItem&amp;lt;T&amp;gt;&amp;gt; _freeItems = &lt;br /&gt;      new ConcurrentQueue&amp;lt;PoolItem&amp;lt;T&amp;gt;&amp;gt;();&lt;br /&gt;   private ConcurrentQueue&amp;lt;AutoResetEvent&amp;gt; _waitLocks = &lt;br /&gt;      new ConcurrentQueue&amp;lt;AutoResetEvent&amp;gt;();&lt;br /&gt;   private ConcurrentDictionary&amp;lt;AutoResetEvent, PoolItem&amp;lt;T&amp;gt;&amp;gt; _syncContext =&lt;br /&gt;      new ConcurrentDictionary&amp;lt;AutoResetEvent, PoolItem&amp;lt;T&amp;gt;&amp;gt;();&lt;br /&gt;&lt;br /&gt;   public Action&amp;lt;T&amp;gt; CleanupPoolItem { get; set; }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Gets the current count of items in the pool&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   public int Count { get; private set; }&lt;br /&gt;&lt;br /&gt;   public void Dispose() {&lt;br /&gt;      lock (this) {&lt;br /&gt;         if (Count != _freeItems.Count)&lt;br /&gt;            throw new InvalidOperationException(&lt;br /&gt;               "Cannot dispose the resource pool while one or more pooled "&lt;br /&gt;               + "items are in use");&lt;br /&gt;&lt;br /&gt;         foreach (var poolItem in _freeItems) {&lt;br /&gt;            Action&amp;lt;T&amp;gt; cleanMethod = CleanupPoolItem;&lt;br /&gt;            if (cleanMethod != null)&lt;br /&gt;               CleanupPoolItem(poolItem.Resource);&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;         Count = 0;&lt;br /&gt;         _freeItems = null;&lt;br /&gt;         _waitLocks = null;&lt;br /&gt;         _syncContext = null;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Gets a free resource from the pool. If no free items available this method &lt;br /&gt;   /// tries to create a new item. If no new item could be created this method &lt;br /&gt;   /// waits until another thread frees one resource.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;returns&amp;gt;A resource item&amp;lt;/returns&amp;gt;&lt;br /&gt;   public PoolItem&amp;lt;T&amp;gt; GetItem() {&lt;br /&gt;      PoolItem&amp;lt;T&amp;gt; item;&lt;br /&gt;&lt;br /&gt;      // try to get an item&lt;br /&gt;      if (!TryGetItem(out item)) {&lt;br /&gt;         AutoResetEvent waitLock = null;&lt;br /&gt;&lt;br /&gt;         lock (this) {&lt;br /&gt;            // try to get an entry in exclusive mode&lt;br /&gt;            if (!TryGetItem(out item)) {&lt;br /&gt;               // no item available, create a wait lock and enqueue it&lt;br /&gt;               waitLock = new AutoResetEvent(false);&lt;br /&gt;               _waitLocks.Enqueue(waitLock);&lt;br /&gt;            }&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;         if (waitLock != null) {&lt;br /&gt;            // wait until a new item is available&lt;br /&gt;            waitLock.WaitOne();&lt;br /&gt;            _syncContext.TryRemove(waitLock, out item);&lt;br /&gt;            waitLock.Dispose();&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      return item;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private bool TryGetItem(out PoolItem&amp;lt;T&amp;gt; item) {&lt;br /&gt;      // try to get an already pooled resource&lt;br /&gt;      if (_freeItems.TryDequeue(out item))&lt;br /&gt;         return true;&lt;br /&gt;&lt;br /&gt;      lock (this) {&lt;br /&gt;         // try to create a new resource&lt;br /&gt;         T resource = _factoryMethod(this);&lt;br /&gt;         if (resource == null &amp;amp;&amp;amp; Count == 0)&lt;br /&gt;            throw new InvalidOperationException("Pool empty and no item created");&lt;br /&gt;&lt;br /&gt;         if (resource != null) {&lt;br /&gt;            // a new resource was created and can be returned&lt;br /&gt;            Count++;&lt;br /&gt;            item = new PoolItem&amp;lt;T&amp;gt;(this, resource);&lt;br /&gt;         }&lt;br /&gt;         else {&lt;br /&gt;            // no items available to return at the moment&lt;br /&gt;            item = null;&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;         return item != null;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Called from &amp;lt;see cref="PoolItem{T}"/&amp;gt; to free previously taked resources&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="resource"&amp;gt;The resource to send back into the pool.&amp;lt;/param&amp;gt;&lt;br /&gt;   internal void SendBackToPool(T resource) {&lt;br /&gt;      lock (this) {&lt;br /&gt;         PoolItem&amp;lt;T&amp;gt; item = new PoolItem&amp;lt;T&amp;gt;(this, resource);&lt;br /&gt;         AutoResetEvent waitLock;&lt;br /&gt;&lt;br /&gt;         if (_waitLocks.TryDequeue(out waitLock)) {&lt;br /&gt;            _syncContext.TryAdd(waitLock, item);&lt;br /&gt;            waitLock.Set();&lt;br /&gt;         }&lt;br /&gt;         else {&lt;br /&gt;            _freeItems.Enqueue(item);&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you see, the &lt;i&gt;ResourcePool&amp;lt;T&amp;gt;&lt;/i&gt; returns &lt;i&gt;PoolItem&amp;lt;T&amp;gt;&lt;/i&gt; objects that hold a reference of the pooled resources. The pool does not need to become initialized with any resource items, new resource items become lazy initialized when (if) needed. Therefore the pool requires a factory method provided at construction. This method becomes called whenever a new resource is requested and no free resources are currently available. If the factory method returns &lt;i&gt;null&lt;/i&gt; the requesting thread becomes suspended until another thread releases a used resource.&lt;br /&gt;&lt;br/&gt;&lt;h3&gt;Usage&lt;/h3&gt;The pool can be used out of the box.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;class MyResource {&lt;br /&gt;   public void DoSomething() { }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void SampleUsage() {&lt;br /&gt;   ResourcePool&amp;lt;MyResource&amp;gt; pool = new ResourcePool&amp;lt;MyResource&amp;gt;(CreateResource);&lt;br /&gt;&lt;br /&gt;   using (var poolItem = pool.GetItem()) {&lt;br /&gt;      MyResource resource = poolItem.Resource;&lt;br /&gt;      resource.DoSomething();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static MyResource CreateResource(ResourcePool&amp;lt;MyResource&amp;gt; pool) {&lt;br /&gt;   return pool.Count &amp;lt; 3 ? new MyResource() : null;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However, if used at many positions in your system I'd suggest to wrap it into a custom pool class. This pool can return a wrapper of the real resources that provide a more specific interface to the consumer. This wrapper can hold an internal reference to a &lt;i&gt;PoolItem&amp;lt;T&amp;gt;&lt;/i&gt; and implement &lt;i&gt;IDisposable&lt;/i&gt; to free the resources back into the pool when not needed anymore.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;// ==========================================================&lt;br /&gt;// The real resource&lt;br /&gt;class InternalResource {&lt;br /&gt;   public void DoSomething() { }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// ==========================================================&lt;br /&gt;// The external wrapper returned to the consumer&lt;br /&gt;class MyResource : IDisposable {&lt;br /&gt;   private PoolItem&amp;lt;InternalResource&amp;gt; _poolItem;&lt;br /&gt;&lt;br /&gt;   public MyResource(PoolItem&amp;lt;InternalResource&amp;gt; poolItem) {&lt;br /&gt;      _poolItem = poolItem;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void DoSomething() {&lt;br /&gt;      _poolItem.Resource.DoSomething();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void Dispose() {&lt;br /&gt;      _poolItem.Dispose();&lt;br /&gt;      _poolItem = null;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// ==========================================================&lt;br /&gt;// The custom pool&lt;br /&gt;class MyPool {&lt;br /&gt;   private ResourcePool&amp;lt;InternalResource&amp;gt; _pool;&lt;br /&gt;&lt;br /&gt;   public MyPool() {&lt;br /&gt;      _pool = new ResourcePool&amp;lt;InternalResource&amp;gt;(CreateResource);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public MyResource GetItem() {&lt;br /&gt;      return new MyResource(_pool.GetItem());&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private InternalResource CreateResource(ResourcePool&amp;lt;InternalResource&amp;gt; pool) {&lt;br /&gt;      return pool.Count &amp;lt; 3 ? new InternalResource() : null;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// ==========================================================&lt;br /&gt;// Sample usage&lt;br /&gt;[Test]&lt;br /&gt;public void SampleUsage() {&lt;br /&gt;   MyPool pool = new MyPool();&lt;br /&gt;&lt;br /&gt;   using (MyResource resource = pool.GetItem()) {&lt;br /&gt;      resource.DoSomething();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here are the files for download:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/ResourcePool.cs?attredirects=0&amp;amp;d=1"&gt;ResourcePool.cs&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/PoolItem.cs?attredirects=0&amp;amp;d=1"&gt;PoolItem.cs&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://sites.google.com/site/florianreischl/blogspot-files/ResourcePoolUnitTest.cs?attredirects=0&amp;amp;d=1"&gt;ResourcePoolUnitTest.cs&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I hope the pool can help you to solve a few of your issues, as it did to me.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-4359614311023899351?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/4359614311023899351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2011/08/generic-c-resource-pool.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/4359614311023899351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/4359614311023899351'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2011/08/generic-c-resource-pool.html' title='Generic C# Resource Pool'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-fW2xw_BTsW0/TkJP5n0lgLI/AAAAAAAAAH0/G1uFQBNddU8/s72-c/ResourcePool.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-729121155373691149</id><published>2011-08-03T14:09:00.000-07:00</published><updated>2011-09-02T04:58:27.524-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><title type='text'>Object reference not set to an instance of an object</title><content type='html'>We all know, and &lt;i&gt;love&lt;/i&gt;, this meaningful message from &lt;i&gt;somewhere inside&lt;/i&gt; of a system.&lt;br/&gt;Luckily I can say, in my last projects I became able to almost eliminate those failures - without a 100% unit test code coverage. (Those outside there who say, 100% code coverage by unit tests is a must must, please don't flame me. I'm a big fan of well tested software, but I guess I'm not yet &lt;i&gt;ready&lt;/i&gt; for 100% coverage ;-).)&lt;br/&gt;&lt;br/&gt;My solution for this old enemy was much easier than some might think. It was done by a simple coding convention. Don't get me wrong, I don't like hundreds of rules about how to write code. In my current project we've got less than 10 project internal coding conventions. Developing large software systems is some kind of a creative work and I think to many rules can eliminate the creativity of developers. I say every experienced developer should be able to write code that others can read and should be able to read code of others.&lt;br/&gt;&lt;br&gt;Our new rule to get rid of null reference exceptions was simply:&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Get-methods never return null.&lt;/b&gt; They return a valid value or it throws an exception.&lt;br/&gt;&lt;br/&gt;This does not mean that our system throws thousands of exceptions per minute. It also means that it is still possible to &lt;i&gt;unsuccessfully try&lt;/i&gt; to get data from a method without an exception, we just do this different.&lt;br/&gt;&lt;br/&gt;In old projects, code like this was a main part of daily business:&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;Customer customer = dataSource.GetCustomerById(1234);&lt;br /&gt;if (customer != null) {&lt;br /&gt;   customer.DoSomething();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;This is nice code and works perfectly. Though, what if someone (me?) ever forgets to check if the method returned &amp;lt;null&amp;gt;? In this case it becomes only a question of time to see our old &lt;i&gt;friend&lt;/i&gt; in a log file or - even worse - in a dialog shown to the user.&lt;br/&gt;To avoid try-catch blocks over and over and avoid NullReferenceExceptions we simply established the &lt;i&gt;TryGet&lt;/i&gt; pattern used by .NET classes like the Dictionary&amp;lt;T,V&amp;gt;. Instead of a possibly null returning Get-method we use a TryGet-method that returns a bool value indicating if our try to get something was successful or not.&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public bool TryGetCustomerById(int id, out Customer customer) {&lt;br /&gt;   using (var connection = CreateOpenConnection())&lt;br /&gt;   using (var command = CreateProcCommand(connection, "GetCustomerById")) {&lt;br /&gt;      command.Parameters.Add("@id", SqlDbType.Int).Value = id;&lt;br /&gt;&lt;br /&gt;      using (var reader = command.ExecuteReader(CommandBehavior.SingleRow)) {&lt;br /&gt;         if (reader.Read()) {&lt;br /&gt;            customer = new Customer();&lt;br /&gt;            customer.Id = id;&lt;br /&gt;            customer.Name = (string)reader["Name"];&lt;br /&gt;         }&lt;br /&gt;         else {&lt;br /&gt;            customer = null;&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;   return customer != null;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;Plus, if really needed, a Get-method that utilizes the TryGet-method and throws an exception if the search was unsuccessful.&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public Customer GetCustomerById(int id) {&lt;br /&gt;   Customer customer;&lt;br /&gt;   if (!TryGetCustomerById(id, out customer))&lt;br /&gt;      throw new EntityNotFoundException(&lt;br /&gt;         string.Format("Cannot find customer with id {0}", id));&lt;br /&gt;   return customer;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;However, in many cases we don't need the Get-methods any more and in a few other cases we don't need the TryGet-methods since something must be wrong if the requested information is not available and a (meaningful) exception is a must.&lt;br/&gt;&lt;br/&gt;This simple change to a TryGet-method changes our consuming library to something like this:&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;Customer customer;&lt;br /&gt;if (dataSource.TryGetCustomerById(123, out customer)) {&lt;br /&gt;   customer.DoSomething();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Some might argue "we still need the check for a result", and they are correct. &lt;b&gt;But&lt;/b&gt;, this is a psychological thing. Calling a method that is called Try... clearly tells the consumer, that this call can return without a result. Even more. Sometimes, when it is okay if the method does not return a value, a developer might leave out the if-condition at the point where (s)he calls a TryGet-method. In those cases I saw other developers asking "But you call a Try-method and you don't check for the null value, are you sure??".&lt;br/&gt;&lt;br/&gt;In cases where a method can return more than one item, like &lt;i&gt;GetCustomersForCountry&lt;/i&gt;, we say it is valid to return an empty list. This is because of two reasons, an empty list is not null and most of the time those calls are followed by a loop that will not be entered for an empty list. However, if we call a method that returns a list and we only need the first item we should consider to add an additional method that returns only one item (like GetFirstCustomerForCountry). Another solution is an extension method "IEnumerable&amp;lt;T&amp;gt;.TryGetFirst(out T item)" and we are back in our style.&lt;br/&gt;&lt;br/&gt;For sure, the samples I used here, to get data from some kind of data source are only one of many parts in a system where we find Get-methods. We use this pattern for all methods we write, independent if it works with a data source or any other objects. And we are doin' good with it.&lt;br/&gt;&lt;br/&gt;As I said, every now and then we still see a NullReferenceExcption, but I guess there have been about 2 or 3 over the last 5 months of intensive development and testing. All in development or test environment, none in production. Plus, if this happens, we know there are only two options how to fix it. Either add the missing if-clause around the call of a TryGet-method (didn't happen over the last year) or change the null returning Get-method.&lt;br/&gt;&lt;br/&gt;Probably I'm the only one who ever had problems with null reference exceptions but, for some reason, it feels like I'm not ;-). I can say we are truly on a point where we can call this old problem (almost) gone.&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-729121155373691149?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/729121155373691149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2011/08/object-reference-not-set-to-instance-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/729121155373691149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/729121155373691149'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2011/08/object-reference-not-set-to-instance-of.html' title='Object reference not set to an instance of an object'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-4623203643610209224</id><published>2011-07-30T12:38:00.000-07:00</published><updated>2011-07-30T12:38:34.527-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><category scheme='http://www.blogger.com/atom/ns#' term='abstraction'/><title type='text'>How to Use 3rd-Party Components</title><content type='html'>Long time ago since my last blog, but I had to concentrate on some other things. Guess it's time to get back here :-).&lt;br/&gt;&lt;br/&gt;After two failed tries of two, more advanced topics, I decided to write about some more basic stuff.&lt;br/&gt;&lt;br/&gt;Let's talk about how to correctly use 3rd-Party components in your software? However, even if this topic is some kind of basic for advanced developers and architects, it's a very important practice in my opinion.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;What Means 3rd-Party Component Here?&lt;/h3&gt;Sure, everybody has a idea of "3rd-Party Components", but I'm not just talking about guerilla frameworks. I'm talking about every component that is not, either part of the stable part of the .NET framework or part of your own project.&lt;br/&gt;&lt;br/&gt;This includes:&lt;ul&gt;&lt;li&gt;Web-Services. In a SOA environment even those of the own project to truly &lt;i&gt;live&lt;/i&gt; the loose coupling concept&lt;/li&gt;&lt;li&gt;Data Access Layers (DAL) like Entity Framework or NHibernate&lt;/li&gt;&lt;li&gt;New or still changing and complex parts of the .NET framework, like Workflow Foundation (WF) or Windows Communication Foundation (WCF) on client side&lt;/li&gt;&lt;li&gt;Independent, true 3rd-party frameworks like log4net, Microsoft Enterprise Library (MEL) and any other library from the web or another ISV&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;This does not include:&lt;ul&gt;&lt;li&gt;.NET framework core components&lt;/li&gt;&lt;li&gt;Technologies like Windows Presentation Foundation (WPF) or Silverlight, since the whole application (a GUI) does not use the technology as a component but is completely based on it. It would be way to much (mostly senseless) effort to tailor an own framework over an existing one that is basis for the complete application&lt;/li&gt;&lt;li&gt;WCF on server side&lt;/li&gt;&lt;li&gt;Helper libraries of the company or project you are working at&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;A brief explanation for the difference of WCF on client and server side: &lt;br/&gt;&lt;br/&gt;When using WCF on server side, the whole process is based on this technology (like WPF in case of GUIs). If you ever need to change the technology, you will usually have to rewrite the whole service, independent of how lose you are coupled to WCF or not.&lt;br/&gt;&lt;br/&gt;When using WCF on client side, the consumed service is usually just one component that could be replaced. E.g. you could replace a data web-service or a service that does some calculations with a local DLL. In this case it should be possible to replace the consumed web-service with any other technology, or even another web-service library.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Dangerous Ways to Consume 3rd-Party Components&lt;/h3&gt;I'm sure everybody has already seen things source code like...Log4net&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public class MyApp {&lt;br /&gt;   private static readonly ILog _log = LogManager.GetLogger(typeof(MyApp));&lt;br /&gt;&lt;br /&gt;   static void Main(string[] args) {&lt;br /&gt;      BasicConfigurator.Configure();&lt;br /&gt;&lt;br /&gt;      _log.Info("Entering application.");&lt;br /&gt;      Bar bar = new Bar();&lt;br /&gt;      bar.DoIt();&lt;br /&gt;      _log.Info("Exiting application.");&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Entity framework&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;using (var context = new MyEntityFrameworkContext()) {&lt;br /&gt;   var customer = context.Customers.Where(c =&gt; c.Code == "ALFKI").First();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;or MEL Unity (sample from MEL help)&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;IUnityContainer myContainer = new UnityContainer();&lt;br /&gt;myContainer.RegisterType&amp;lt;ILogger, FileLogger&amp;gt;();&lt;br /&gt;myContainer.RegisterType&amp;lt;ILogger, FastFileLogger&amp;gt;("FastLogger");&lt;br /&gt;// ...&lt;br /&gt;ILogger myLogger = myContainer.Resolve&amp;lt;ILogger&amp;gt;();&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;At first sight, this all looks good, pragmatic and straight forward. However, this approach &lt;i&gt;can&lt;/i&gt; bring up serious problems. Why? The used framework/library might fit perfectly at the moment, but this can (and sometimes does) change over the years. Software systems are usually made to stay for, at least, 8 years until it is time to redesign it. Sure, if the software doesn't need many changes, it can be used for longer time.&lt;br/&gt;&lt;br/&gt;What if, either the component becomes updated and its interface(s) changes? What if you upgrade your system to a new platform (e.g. a new .NET framework) and the component doesn't work on this platform? What if new technologies come up and are not covered by the component you are using?&lt;/br&gt;You can say "Hey, I'm sure that wont happen, that's all doomsaying", but how about this:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;Microsoft completely redesigned the Workflow Foundation from .NET 3 to .NET 4&lt;/li&gt;&lt;li&gt;ASP.NET web-services are almost obsolete and will not be extended due to WCF&lt;/li&gt;&lt;li&gt;LINQ-to-SQL will not be extended any more&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Dino_Esposito"&gt;Dino Esposito&lt;/a&gt; and &lt;a href="http://blogs.ugidotnet.org/mrbrightside/Default.aspx"&gt;Andrea Saltarello&lt;/a&gt; wrote in their book &lt;a href="http://www.microsoft.com/learning/en/us/book.aspx?ID=12863&amp;locale=en-us"&gt;Architecting Applications for the Enterprise&lt;/a&gt; how they had to redesign almost their whole system as they had to switch from NHibernate to Entity Framework 1&lt;/li&gt;&lt;/ul&gt;As you see, it is not uncommon that changes happen over the lifetime of a software system. It's up to us to be armed when those things happen&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Which Options do we have?&lt;/h3&gt;Often, it's not too hard to stay relatively independent of external components.&lt;br/&gt;&lt;br/&gt;In case of components like log4net or MEL Unity we just have to create a wrapper class that becomes created by a factory class or a DI (sure, we will not create MEL Unity from another DI container..). The following snippets are just pseudo code to indicate what I'm talking about.&lt;br/&gt;&lt;br/&gt;Wrap log4net:&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public interface ILogger {&lt;br /&gt;   void Info(string message);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Log4NetLogger : ILogger {&lt;br /&gt;   private static readonly ILog _log = LogManager.GetLogger("MyApp");&lt;br /&gt;&lt;br /&gt;   void ILogger.Info(string message) {&lt;br /&gt;      _log.Info(message);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Wrap unity:&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public interface IDependencyContainer {&lt;br /&gt;   T Resolve&amp;lt;T&amp;gt;();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class UnityDependencyContainer : IDependencyContainer {&lt;br /&gt;   IUnityContainer _unity = new UnityContainer();&lt;br /&gt;&lt;br /&gt;   T IDependencyContainer.Resolve&amp;lt;T&amp;gt;() {&lt;br /&gt;      return _unity.Resolve&amp;lt;T&amp;gt;();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class DependendcyContainerFactory {&lt;br /&gt;   public static IDependencyContainer Create() {&lt;br /&gt;      // if ever using more than one container, use configuration &lt;br /&gt;      // or anything else here to switch between them&lt;br /&gt;      return new UnityDependencyContainer();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;In case of DAL frameworks like EF we need to think one step further. EF comes up with this cool LINQ-to-EF feature that makes database queries quite fancy. Though, do we really need this in applications/libraries that consume our DAL? Does it make sense that a GUI app knows how to query all current orders of a customer like "context.Orders.Where(o =&amp;gt; o.Customer.Id == myCustomer.Id)"? What if the relation becomes ever changed on database level and it is not possible to change the EDL to provide this relation any more? I'd say LINQ-to-EF is a nice feature &lt;b&gt;within&lt;/b&gt; the DAL, but should not be used from consumers.&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public interface IDataContext {&lt;br /&gt;   IEnumerable&amp;lt;Order&amp;gt; GetOrdersForCustomer(Customer customer);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class MyEfDataContext : IDataContext {&lt;br /&gt;   public IEnumerable&amp;lt;Order&amp;gt; GetOrdersForCustomer(Customer customer) {&lt;br /&gt;      using (var ctx = new MyEfContext()) {&lt;br /&gt;         return ctx.Where(o =&amp;gt; o.Customer.Id == customer.Id).ToList();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Now, everybody can safely use the method to get the Orders and if the relation ever changes, it needs to be changed at only one position and non of the consumers will notice it.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Working Safely&lt;/h3&gt;And now, after writing a few wrapper classes and thinking about how to use features (like LINQ-to-EF), we are armed to use all those nice components in our application without the danger to be controlled by them.&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;public class MyApp {&lt;br /&gt;   public MyApp() {&lt;br /&gt;      _container = DependendcyContainerFactory.Create();&lt;br /&gt;      _logger = _container.Resolve&amp;lt;ILogger&amp;gt;();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private IDependencyContainer _container;&lt;br /&gt;   private ILogger _logger;&lt;br /&gt;&lt;br /&gt;   public void DoWork() {&lt;br /&gt;      _logger.Info("foo");&lt;br /&gt;      IDataContext myData = _container.Resolve&amp;lt;IDataContext&amp;gt;();&lt;br /&gt;      Customer customer = GetCustomerToWorkWith();&lt;br /&gt;      var orders = myData.GetOrdersForCustomer(customer);&lt;br /&gt;      _logger.Info("bar");&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private Customer GetCustomerToWorkWith() {&lt;br /&gt;      // usually the implementation to get the customer&lt;br /&gt;      return null;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;If there will ever be a new, better framework. If there will ever be a feature that is not covered by our components. If there will ever be any other reason to switch to another technology. We are able to switch without redesigning the whole application.&lt;br/&gt;&lt;br/&gt;Don't get this all wrong, it is &lt;b&gt;not always easy&lt;/b&gt; to stay independent and switching to another 3rd-party component will &lt;b&gt;always cause effort&lt;/b&gt;. But usually this effort is much less if our applications are designed to be ready for changes.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;i&gt;(It felt good to write but, after one year since my last blog, it also felt like not being perfect. Seems like I need some practice after this time, so please be patient with me for this post..)&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-4623203643610209224?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/4623203643610209224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2011/07/how-to-use-3rd-party-components.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/4623203643610209224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/4623203643610209224'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2011/07/how-to-use-3rd-party-components.html' title='How to Use 3rd-Party Components'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-1975619980401473802</id><published>2010-07-31T05:58:00.000-07:00</published><updated>2010-07-31T06:35:46.733-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='Workflows'/><category scheme='http://www.blogger.com/atom/ns#' term='.net 4.0'/><category scheme='http://www.blogger.com/atom/ns#' term='BPM'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='WF'/><title type='text'>Business Process Modeling (BPM) with .NET Workflow Foundation (WF) 4.0</title><content type='html'>I'm currently reading the book &lt;a href="http://www.amazon.com/Pro-WF-Windows-Workflow-NET/dp/1430227214/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1280572436&amp;amp;sr=1-1"&gt;Pro WF: Windows Workflow in .NET 4&lt;/a&gt;. As a short intermediate review: It's a great resource! I'll write a complete review when I'm done with the rest of the book. I'll also come up with a post that describes a complete overview of Workflow Foundation (WF) 4.0.&lt;br /&gt;&lt;br /&gt;This post provides a simple example how WF can be used by our clients to apply real Business Process Modeling (BPM).&lt;br /&gt;&lt;br /&gt;Guess we are developing a sales order system. Depending on an orders net-amount the order gets a discount. The calculation of this discount is usually best done within source code (at least in my opinion). So here is a class that represents our default implementation.&lt;br /&gt;&lt;pre class="brush: csharp"&gt;using System.Activities;&lt;br /&gt;&lt;br /&gt;namespace WfActivityLibrary1 {&lt;br /&gt;   public sealed class DefaultDiscount : CodeActivity {&lt;br /&gt;      [RequiredArgument]&lt;br /&gt;      public InArgument&amp;lt;Order&amp;gt; Order { get; set; }&lt;br /&gt;&lt;br /&gt;      protected override void Execute(CodeActivityContext context) {&lt;br /&gt;         Order order = Order.Get(context);&lt;br /&gt;&lt;br /&gt;         if (order.NetAmount &amp;gt;= 1000)&lt;br /&gt;            order.Discount = order.NetAmount * 0.2m;&lt;br /&gt;         else if (order.NetAmount &amp;gt;= 500)&lt;br /&gt;            order.Discount = order.NetAmount * 0.1m;&lt;br /&gt;         else if (order.NetAmount &amp;gt;= 100)&lt;br /&gt;            order.Discount = order.NetAmount * 0.05m;&lt;br /&gt;         else&lt;br /&gt;            order.Discount = 0m;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The used base class &lt;i&gt;CodeActivity&lt;/i&gt; represents one of the Workflow Foundation base classes that can be used to implement custom workflow activities. Usually I'd move the business logic into a class within the Business Logic Layer (BLL) and consume that class within the WF activity. But this would increase the complexity of this sample with additional layers and without any real worth about working with WF, what's the topic of this post.&lt;br /&gt;&lt;br /&gt;The problem with discounting is, operational business is very dynamic and the client usually needs to be able to provide selling campaigns to her/his customer. A campaign can be "20% for everything" or "50% of for premium customers".&lt;br /&gt;&lt;br /&gt;Until now, this was the point where we started to create dozens of mapping tables and much more classes, containing hundreds of &lt;i&gt;if&lt;/i&gt;-statements, which covered the different types of clients discounts. The client got some new masks within the application to manage all those new master data or (worse) a way to import some outside maintained Excel sheets.&lt;br /&gt;&lt;br /&gt;However, what if the client wants to provide a new discount related on information that are not yet covered by our "discount calculation"-subsystem within our software? We started to add more master data tables, more classes, more &lt;i&gt;if&lt;/i&gt;-statements and more master data masks within the application.&lt;br /&gt;Humans are creative. Especially sales people, when they try to find a new ways to sales their products. (What's a good thing!) So requirements like calculation of discounts for selling-out campaigns are often spirals that never end.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Business Process Modeling&lt;/h3&gt;Often clients do not for complicated master data table relations or huge complexity within their system (which is often expensive to realize). They don't understand why it is so complicated to combine discount rates dynamically in different ways. And from a workflow based point, they are right though.&lt;br /&gt;&lt;br /&gt;Instead of all those master data tables, and mask, the client often would prefer some way to really dynamically define their discounts with some simple components. That's the point where an application, that supports those features, enters the space of Business Process Modeling (BPM). BPM enabled software represents a huge benefit to the client, since (s)he does not longer need to specify a new change request for the software vendor whenever business changes. Instead of immutable behavior, the software is able to be adopted into the changing business processes.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;BPM with WF&lt;/h3&gt;Based on our initial sample, let's take our already existing "Default Discount" workflow activity and one additional activity called "Fix Rate Discount". The "Fix Rate Discount" gets two arguments:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Order: The order to be discounted&lt;/li&gt;&lt;li&gt;Percentage: The percentage rate to apply to the order&lt;/li&gt;&lt;/ul&gt;I kept the source code of the "Fix Rate Discount" activity away, since it is really simple and does not relate to business modeling at all.&lt;br /&gt;Armed with those two (notice, only two) workflow activities it's time to review our two selling-out campaigns.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;20% for everything&lt;/li&gt;&lt;li&gt;50% of for premium customers&lt;/li&gt;&lt;/ul&gt;WF provides the possibility to define new workflows not only in Visual Studio but in any kind of .NET client application, simply by hosting a special WF designer control. So we can include this control into our application (or an external BPM module) and give the client the possibility to model their business by utilizing any defined activities. Even more, each new workflow represents an activity too and can be reused within any other workflow.&lt;br /&gt;&lt;br /&gt;WF provides two different kinds of diagrams. Sequence diagrams represent a sequence of activities, executed top down. Flowchart diagrams are like any kind of well known flow chart out of tools like common BPM tools, Microsoft Visio, and most other modeling tools. Both diagram types can be easily combined with each other. Both diagram types support activities like &lt;i&gt;"if"&lt;/i&gt;-decisions or several different loops.&lt;br /&gt;&lt;br /&gt;I've chosen a sequence diagram for our "20% for everything" selling-off.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_hBTxNhEL4oY/TFQW4vLX_vI/AAAAAAAAAGc/r7bK-OE5pSw/s1600/wf_sequence.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_hBTxNhEL4oY/TFQW4vLX_vI/AAAAAAAAAGc/r7bK-OE5pSw/s640/wf_sequence.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Here you see an excerpt of the WF workflow designer and related toolboxes. Certainly the main component is the diagram designer. Activities can be dragged into the designer and configured. The left toolbox (in my configuration) shows all workflow activities that are currently available. The properties window on the right side can be used to configure distinct activities within a diagram and exchange data. The tool-window at the bottom is used to define input and output arguments of the current workflow. For instance, the current workflow expects an input argument of type "Order" called "OrderToDiscount". Those arguments are provided at runtime when the system calls the workflow. Within the diagram the "DefaultDiscount" activity represents the systems implemented default discount calculation. The "Add 20% Discount" activity represents a "FixRateDiscount" activity where I changed the name to be more meaningful within the diagram.&lt;br /&gt;For the "50% of for premium customers" workflow, I've chosen a Flowchart diagram. Not because it wouldn't be possible to do this with a Sequence diagram, but to show the other diagram type.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_hBTxNhEL4oY/TFQkMun5jKI/AAAAAAAAAG0/KLEd0PNbszM/s1600/wf_flowchart.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_hBTxNhEL4oY/TFQkMun5jKI/AAAAAAAAAG0/KLEd0PNbszM/s640/wf_flowchart.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;The "Decision" activity represents an "if"-decision that determines if the customers category is "Premium". For sure, in a real system this information evaluation should be encapsulated in a custom activity. The "DefaultDiscount" represents our system default discount calculation. The "50% Discount" activity is another instance of our "FixRateDiscount" activity.&lt;br /&gt;&lt;h3&gt;Instrumentation Instead of Development&lt;/h3&gt;Nevertheless, be careful with too many logic within those workflows. Due to some very powerful activities like &lt;i&gt;"Assign"&lt;/i&gt; to assign any value to any variable or property of an object or &lt;i&gt;"Invoke"&lt;/i&gt; to invoke any method on an object instance, you can use WF to &lt;i&gt;develop&lt;/i&gt; almost everything. In my opinion, this is the wrong way to use workflow engines. Those tasks are usually better placed in source code.&lt;br /&gt;&lt;br /&gt;I see a huge strength in workflows to enable clients to change the processing behavior of a system. I don't see a worth in letting the client &lt;i&gt;develop&lt;/i&gt; her/his system. Usually they neither do have the skills to do this, nor they are interested in tiny low level tasks within their models.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-1975619980401473802?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/1975619980401473802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/07/business-process-modeling-bpm-with-net.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/1975619980401473802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/1975619980401473802'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/07/business-process-modeling-bpm-with-net.html' title='Business Process Modeling (BPM) with .NET Workflow Foundation (WF) 4.0'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_hBTxNhEL4oY/TFQW4vLX_vI/AAAAAAAAAGc/r7bK-OE5pSw/s72-c/wf_sequence.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-7209955789799305752</id><published>2010-07-19T05:05:00.000-07:00</published><updated>2010-07-19T05:10:00.667-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>If You Cannot Use Identities; Cache Your Ids</title><content type='html'>Sometimes it is not possible to use IDENTITY columns in database tables. Unfortunately, one of the most common approaches to handle new IDs in non IDENTITY columns is working with MAX(). I just saw this yet another time in a blog post I don't want to refer here. In my opinion, the generation of unique ID values is quiet basic but should be done correct, so this blog post is all about this topic.&lt;br /&gt;&lt;br /&gt;If you are able to use IDENTITIES in all tables, you are find and you can finish reading here. :-)&lt;br/&gt;&lt;h3&gt;Reasons Not To Work With Identity Columns&lt;/h3&gt;One reason might be, that the used framework does not support them, like Entity Framework in combination with SQL Server Compact. SQL Server Compact does not support batch execution, so every query allows only one SQL statement and EF does not support a second query for each INSERT to determine the last generated IDENTITY value.&lt;br /&gt;&lt;br /&gt;Another reason not to work with IDENTITY columns are scenarios where computed IDs are required, like in distributed systems. I used them to guarantee a unique PRIMARY KEY over all databases (all over the world) where the first part of the primary key was an incrementing BIGINT value and the second part was a SMALLINT, describing the database where the table row was created. Some of you might argue, that I would have also been able to use a Guid, however I still don't like them in databases since they are way too large and too slow.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The MAX() Approach&lt;/h3&gt;A very common approach to generate new ID values is to select the currently maximal value of the table where new rows have to be inserted.&lt;br /&gt;&lt;br /&gt;Here a plain SQL sample.&lt;br /&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;-- ======================================================================&lt;br /&gt;CREATE TABLE Orders (&lt;br /&gt;   Id INT NOT NULL PRIMARY KEY CLUSTERED&lt;br /&gt;   ,OrderDate DATETIME2&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;-- ======================================================================&lt;br /&gt;-- some existing rows&lt;br /&gt;INSERT INTO Orders VALUES (1, SYSDATETIME());&lt;br /&gt;&lt;br /&gt;-- ======================================================================&lt;br /&gt;-- generate new ID values, using MAX&lt;br /&gt;DECLARE @newId INT;&lt;br /&gt;&lt;br /&gt;-- select current maximal ID + 1&lt;br /&gt;SELECT @newId = ISNULL(MAX(Id), 0) + 1 FROM Orders;&lt;br /&gt;&lt;br /&gt;INSERT INTO Orders VALUES(@newId, SYSDATETIME());&lt;br /&gt;&lt;/pre&gt;Unfortunately, this approach has some issues. First, let's have a look at the performance. Each call of MAX() causes an index scan of the primary key, as shown in the below execution plan. SQL Server 2008 does a great job, avoiding to scan the whole index, however this scan for each new row should be avoided.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_hBTxNhEL4oY/TEQQJ5iIU5I/AAAAAAAAAFs/40teGn0DsHM/s1600/Max_Scan.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="99" src="http://2.bp.blogspot.com/_hBTxNhEL4oY/TEQQJ5iIU5I/AAAAAAAAAFs/40teGn0DsHM/s640/Max_Scan.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The second, more important issues is concurrency. If we are working with SQL Server Compact, this issue does not exist, since the DBMS supports only one current connection at the time ;-). In every other environment, where we have more than one concurrent user connection, we might (and occasionally &lt;b&gt;will&lt;/b&gt;) get an error if there are two concurrent inserts and both connections are at the same time between row 16 and row 18 of the above sample script. Both will get the same MAX ID value from the table, but only one of them can use the new calculated ID for insert. The second one will retrieve a primary key violation.&lt;br /&gt;&lt;br/&gt;&lt;h3&gt;Using an ID Table&lt;/h3&gt;To avoid both previously denoted issues, we can use an ID-table, containing the name of the table to create a new ID for and the next available ID.&lt;pre class="brush: sql;"&gt;&lt;br /&gt;-- ======================================================================&lt;br /&gt;-- id table&lt;br /&gt;CREATE TABLE Ids (&lt;br /&gt;   Name VARCHAR(30) PRIMARY KEY CLUSTERED&lt;br /&gt;   ,NextId BIGINT NOT NULL&lt;br /&gt;);&lt;br /&gt;-- ======================================================================&lt;br /&gt;-- init ids for Orders table&lt;br /&gt;INSERT INTO Ids VALUES('Orders', 1);&lt;br /&gt;GO&lt;br /&gt;-- ======================================================================&lt;br /&gt;DECLARE @id BIGINT;&lt;br /&gt;-- get the next available "Orders" id from Ids table&lt;br /&gt;UPDATE Ids SET&lt;br /&gt;   @id = NextId&lt;br /&gt;   ,NextId += 1&lt;br /&gt;WHERE Name = 'Orders';&lt;br /&gt;&lt;br /&gt;INSERT INTO Orders VALUES(@id, SYSDATETIME());&lt;br /&gt;&lt;/pre&gt;Usually, we would move the ID allocation into a procedure, which I left out for sake of brevity. This already looks like a much better approach, doesn't it?&lt;br/&gt;&lt;br/&gt;However, till now, this solution brings up another issues. Now the whole system has to access (with a write lock) the ID-table for each single row inserted into any other table. This usually causes a system wide performance issue when system is on load. The solution for this problem is to cache IDs as explained below.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;ID Caching&lt;/h3&gt;To avoid the access problem with the ID table, clients can use a caching mechanism. This means each client avoids to allocate new IDs one by one, but always allocates a larger count of IDs in one step and works with them for the next new rows to be inserted.&lt;br/&gt;&lt;br/&gt;The count of IDs to be allocated in one step depends on the client and the count of row it usually creates. A GUI like a web- or windows-application is often fine with an ID cache size of 10 where a data loader process might need a cache size of 1000.&lt;br/&gt;&lt;br/&gt;For sure, this causes that some ids are never used. E.g. if a web application allocates 10 new IDs but the user enters only one new row, 9 IDs are lost. However, this doesn't really matter since primary key IDs are only needed for uniqueness and should never be used as shown sequence in the client.&lt;br/&gt;&lt;br/&gt;The easiest way to allocate new IDs is a simple procedure which gets the name of the table to allocate new IDs for and the count of IDs to be allocated and returns the next available ID to be used.&lt;br/&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;ALTER PROCEDURE AllocateIds&lt;br /&gt;   @nextId BIGINT OUTPUT&lt;br /&gt;   ,@name VARCHAR(30)&lt;br /&gt;   ,@count INT&lt;br /&gt;AS&lt;br /&gt;SET NOCOUNT ON;&lt;br /&gt;&lt;br /&gt;UPDATE Ids SET&lt;br /&gt;   @nextId = NextId&lt;br /&gt;   ,NextId += @count&lt;br /&gt;WHERE Name = @name&lt;br /&gt;GO&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;Client Side Caching&lt;/h3&gt;Caching IDs in a client application is usually quiet easy, as long as the client is stateful like usual web- or windows-applications and most web services.&lt;br/&gt;&lt;br/&gt;This &lt;i&gt;IdGenerator&lt;/i&gt; is a very simple sample of how to cache IDs in the client, utilizing our previously shown stored procedure.&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;static class IdGenerator {&lt;br /&gt;   class IdEntry {&lt;br /&gt;      public long NextId;&lt;br /&gt;      public long MaxId;&lt;br /&gt;   }&lt;br /&gt;   // table depenant cache&lt;br /&gt;   static IDictionary&amp;lt;string, IdEntry&amp;gt; _cache = new Dictionary&amp;lt;string, IdEntry&amp;gt;();&lt;br /&gt;   // connection and allocation information&lt;br /&gt;   static string _connectionString;&lt;br /&gt;   static int _allocationSize;&lt;br /&gt;   // initializes the connection and allocation information&lt;br /&gt;   public static void Init(string connectionString, int allocationSize) {&lt;br /&gt;      _connectionString = connectionString;&lt;br /&gt;      _allocationSize = allocationSize;&lt;br /&gt;   }&lt;br /&gt;   // public interface to allocate new ids&lt;br /&gt;   public static long NextId(string tableName) {&lt;br /&gt;      IdEntry entry = GetEntry(tableName);&lt;br /&gt;      if (entry.NextId &amp;gt; entry.MaxId)&lt;br /&gt;         AllocateNewIds(entry, tableName);&lt;br /&gt;      return entry.NextId++;&lt;br /&gt;   }&lt;br /&gt;   // get an id entry for a specified table&lt;br /&gt;   private static IdEntry GetEntry(string tableName) {&lt;br /&gt;      IdEntry entry;&lt;br /&gt;      if (!_cache.TryGetValue(tableName, out entry)) {&lt;br /&gt;         entry = new IdEntry { NextId = 1 };&lt;br /&gt;         _cache.Add(tableName, entry);&lt;br /&gt;      }&lt;br /&gt;      return entry;&lt;br /&gt;   }&lt;br /&gt;   // allocate new ids from database&lt;br /&gt;   private static void AllocateNewIds(IdEntry entry, string tableName) {&lt;br /&gt;      Console.WriteLine("Allocating new ids from database");&lt;br /&gt;      using (SqlConnection connection = CreateConnection())&lt;br /&gt;      using (SqlCommand command = new SqlCommand("AllocateIds", connection)) {&lt;br /&gt;         command.CommandType = CommandType.StoredProcedure;&lt;br /&gt;&lt;br /&gt;         SqlParameter nextId = command.Parameters.Add("@nextId", SqlDbType.BigInt);&lt;br /&gt;         nextId.Direction = ParameterDirection.Output;&lt;br /&gt;         command.Parameters.Add("@name", SqlDbType.VarChar, 30).Value = tableName;&lt;br /&gt;         command.Parameters.Add("@count", SqlDbType.Int).Value = _allocationSize;&lt;br /&gt;         command.ExecuteNonQuery();&lt;br /&gt;         entry.NextId = (long)nextId.Value;&lt;br /&gt;         entry.MaxId = entry.NextId + _allocationSize - 1;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;   // create a new, open database connection&lt;br /&gt;   private static SqlConnection CreateConnection() {&lt;br /&gt;      SqlConnection connection = new SqlConnection(_connectionString);&lt;br /&gt;      connection.Open();&lt;br /&gt;      return connection;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;... and a sample, how to use the ID generator...&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;IdGenerator.Init("Server=.;Database=Sandbox;Integrated Security=sspi;", 10);&lt;br /&gt;for (int i = 0; i &amp;lt; 100; i++) {&lt;br /&gt;   long id = IdGenerator.NextId("Orders");&lt;br /&gt;   Console.WriteLine(id);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;&lt;h3&gt;ID Tables And T-SQL&lt;/h3&gt;Well, while ID-tables and caching are a good way to go in client applications, they are a bit tricky in T-SQL (and probably in most other SQL dialects). The problem is that T-SQL is stateless and due to this fact it does not support caching, since we don't have that "static" place where we can store our cached IDs.&lt;br/&gt;&lt;br/&gt;One workaround is to create a temp table that looks like the stateful ID-table and represents our "own" cache. But, due to the scope handling of SQL Server it is not possible to move the temp table creation into a procedure, so this workaround is quiet awkward to maintain since all scripts/procedures that want to a client like caching have always to create their temp table by their own.&lt;br/&gt;&lt;br/&gt;However, usually T-SQL scripts should never try to work like clients - in a row based manner, so they should not really need a ID cache. Whenever new rows have to be inserted into a table, the executing procedure/script should determine the full count of needed rows, allocate the required range of IDs and insert all rows in one operation.&lt;br/&gt;&lt;br/&gt;One thing that changes when working with ID-tables is, IDs for single row inserts should be provided from client now. Why? Because of the missing ability to cache IDs in T-SQL. Where we usually had insert procedures lie this...&lt;pre class="brush: sql;"&gt;&lt;br /&gt;CREATE PROCEDURE InsertOrder&lt;br /&gt;   @id INT OUTPUT&lt;br /&gt;   ,@orderDate DATETIME2&lt;br /&gt;AS&lt;br /&gt;   INSERT INTO Orders (OrderDate)&lt;br /&gt;      VALUES (@orderDate);&lt;br /&gt;   SELECT @id = SCOPE_IDENTITY();&lt;br /&gt;&lt;/pre&gt;... we would have to act like this...&lt;pre class="brush: sql;"&gt;&lt;br /&gt;CREATE PROCEDURE InsertOrder&lt;br /&gt;   @id INT OUTPUT&lt;br /&gt;   ,@orderDate DATETIME2&lt;br /&gt;AS&lt;br /&gt;   EXECUTE AllocateIds @id OUTPUT, 'Orders', 1;&lt;br /&gt;   INSERT INTO Orders (Id, OrderDate)&lt;br /&gt;      VALUES (@id, @orderDate);&lt;br /&gt;&lt;/pre&gt;... but this would cause a huge traffic in our ID-table. So it is usually more productive to get the IDs from the client, which can easily handle the caching.&lt;pre class="brush: sql;"&gt;&lt;br /&gt;CREATE PROCEDURE InsertOrder&lt;br /&gt;   @id INT&lt;br /&gt;   ,@orderDate DATETIME2&lt;br /&gt;AS&lt;br /&gt;   INSERT INTO Orders (Id, OrderDate)&lt;br /&gt;      VALUES (@id, @orderDate);&lt;br /&gt;&lt;/pre&gt;Some might say, that they don't want to give clients the force to handle the new primary key values. Though, SQL Server enforces the uniqueness for you ;-) and the price to pay is quiet cheap, compared to the other option.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Stateless Clients&lt;/h3&gt;Stateless clients have almost same issues like T-SQL procedures and scripts. Due to their statelessness, they are usually not able to cache their IDs. The only additional option we got with stateless clients is to move the ID caching into an external resource like a WCF service. If an system has several stateful and several stateless components, it is an option to keep the stateful applications fast by providing a separate ID cache for those that are stateless.&lt;br/&gt;&lt;br/&gt;For sure, you could consume this service also from T-SQL (quiet simple with SQLCLR as I showed &lt;a href="http://florianreischl.blogspot.com/2009/09/query-web-service-with-sqlclr.html"&gt;here&lt;/a&gt;) but SQLCLR to access web services is still rare used and the overhead is usually way larger than directly accessing the ID-table. So, the service should only be used from client side to keep the SQL out of the ID generation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-7209955789799305752?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/7209955789799305752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/07/if-you-cannot-use-identities-cache-your.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7209955789799305752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7209955789799305752'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/07/if-you-cannot-use-identities-cache-your.html' title='If You Cannot Use Identities; Cache Your Ids'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_hBTxNhEL4oY/TEQQJ5iIU5I/AAAAAAAAAFs/40teGn0DsHM/s72-c/Max_Scan.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-7633269653229720403</id><published>2010-07-09T08:33:00.000-07:00</published><updated>2010-07-09T08:34:49.599-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='collaboration'/><title type='text'>Defend Your Code</title><content type='html'>Ever explained a current bug or dirty implementation with one of those sentences?&lt;br/&gt;&lt;ul&gt;&lt;li&gt;"The (project) manager/marketer said, we have to meet the deadline."&lt;/li&gt;&lt;li&gt;"The (project) manager/product owner told you, a quick and dirty solution is okay for now."&lt;/li&gt;&lt;li&gt;"The XYZ told you, we NEED this new feature, no matter how it works behind."&lt;/li&gt;&lt;/ul&gt;Never? Though, I did, not currently but I did.&lt;br/&gt;&lt;br/&gt;Who was responsible to the current problem? It's me. I treated non code-specific requirements over system quality. I did not write the unit test which had found the problem. I did not invest the time for refactoring to ensure a clean implementation. You might argue that &lt;i&gt;somebody else&lt;/i&gt; decided. Nevertheless, it's my, and only my, task to keep the system clean, free of bugs and maintainable.&lt;br/&gt;&lt;br/&gt;I see software projects are like a play and we, all the stakeholders, are the actors/actresses. The part of the marketer is to push forward for new features. Part of the project manager, managers and product owners is to obsess the schedule. And it's our part to defend the code!&lt;br/&gt;&lt;br/&gt;What about "If I did not implement this feature in time, I'd got fired"? Probably not. Most Managers don't want buggy software or software that is hard to maintain for future requirements. Even if they don't say that very clear. Managers, and all other non developing stakeholders, just cannot rate importance of one or more unit tests and have no clue about refactoring (even if they say they do have).&lt;br/&gt;&lt;br/&gt;If I would be an electrican, the building owner and the lead worker would always insist on the deadline. However, if there is no power when the building is done, I'd be the single neck to wreck. No building owner, no lead worker. It would be their part to push forward and it would be my part to make (and keep!) it work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-7633269653229720403?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/7633269653229720403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/07/defend-your-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7633269653229720403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7633269653229720403'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/07/defend-your-code.html' title='Defend Your Code'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-1375751904883391793</id><published>2010-07-07T04:19:00.000-07:00</published><updated>2010-07-09T08:35:02.440-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='ethics'/><category scheme='http://www.blogger.com/atom/ns#' term='collaboration'/><title type='text'>We Are Authors!</title><content type='html'>I just read this statement in &lt;a href="http://www.objectmentor.com/omTeam/martin_r.html"&gt;Robert C. Martin&lt;/a&gt;'s Book &lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1278490742&amp;sr=1-1"&gt;Clean Code&lt;/a&gt; where he primary wrote about "how to write code". However, I see this as a more general thing.&lt;br/&gt;&lt;br/&gt;We are all authors and and we are writing almost all the day. Everything we write will be read by somebody, now or in months, so we really should think about the reader when we are writing. Reading can make people annoyed about the author or grateful to him/her and we should always prefer the latter.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Source Code&lt;/h3&gt;Did you ever see some, &lt;i&gt;so called&lt;/i&gt; "very flexible", solution like this?&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;// get data returns all new users to be created&lt;br /&gt;object[] rows = GetData();&lt;br /&gt;foreach (object[] row in rows) {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // ix 0 represents the new user id&lt;br /&gt;    // ix 1 is not needed&lt;br /&gt;    // ix 2 is the name of the new user&lt;br /&gt;    int i = (int)row[0];&lt;br /&gt;    string n = (string)row[2];&lt;br /&gt;    CreateUser(i, n);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Guess, the author is just sitting right next to you and you are about to add some new features. He tells you that this approach, using untyped &lt;i&gt;object&lt;/i&gt; arrays is very flexible, because you don't have to change the interface if something new comes in.&lt;br/&gt;&lt;br/&gt;I call this completely inflexible. It is impossible to do any change anything within the user structure since it is almost impossible to find the positions where the structure is used.&lt;br/&gt;&lt;br/&gt;How shall I know that &lt;i&gt;GetData&lt;/i&gt; returns users? Does it always return users? Why an array of &lt;i&gt;object&lt;/i&gt; as rows, instead of an &lt;i&gt;ICollection&amp;ltT&amp;gt;&lt;/i&gt; to let the user know what's inside the collection? Why another array of &lt;i&gt;object&lt;/i&gt; as row, instead of a strong typed &lt;i&gt;NewUser&lt;/i&gt; type? Why all the noise comments, instead of self describing variables? What's about "ix 1 is not needed"? Is it always empty until now? Is it reserved for future usage? Am I just not allowed to look into? Why the two empty rows at the beginning of the loop?&lt;br/&gt;&lt;br/&gt;How about this?&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;ICollection&amp;lt;NewUser&amp;gt; newUsers = GetNewUsers();&lt;br /&gt;foreach (NewUser user in newUsers) {&lt;br /&gt;    CreateUser(user.Id, user.UserName);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;This code does exactly the same as the previous, but we don't need any comments. The reader directly knows what's going on and we are able to refactor &lt;i&gt;NewUser&lt;/i&gt; whenever we want because we can find all positions where it is used.&lt;br/&gt;&lt;br/&gt;If I might ask myself, who should ever read my code? The most faithful reader of my code am I. If we have to change some implementation, we realized days, months or years before we start with reading the existing code. We are jump back and forth to find out what happens, which objects are used and how they are composed to hit the target.&lt;br/&gt;&lt;br/&gt;Writing clean source code means to be kind to your readers; especially you.&lt;br/&gt;&lt;h3&gt;T-SQL&lt;/h3&gt;For sure, T-SQL is source code too. However, for me it felt important to write this own subject. Why? Because the most ugly code I've seen was written in T-SQL.&lt;br/&gt;&lt;br/&gt;Ever seen a procedure/script like this?&lt;pre class="brush: sql;"&gt;&lt;br /&gt;insert Into TestData100K SELECT Top(10) id, BitVal, FLOATVAL from TestData10K WHERE &lt;br /&gt;ID &amp;gt; 99&lt;br /&gt;and intval != 1&lt;br /&gt;&lt;/pre&gt;Unfortunately (yes, unfortunately) T-SQL is not case sensitive, so the upper/lower case of statements or even words within statements are often only depends on the occasional twitches of the writers little finger. What about line breaks? How about indention?&lt;br/&gt;&lt;br/&gt;How about this?&lt;br/&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;INSERT INTO TestData100K&lt;br /&gt;SELECT TOP(10) &lt;br /&gt;   Id&lt;br /&gt;   ,BitVal&lt;br /&gt;   ,FloatVal&lt;br /&gt;FROM TestData10K &lt;br /&gt;WHERE ID &amp;gt; 99&lt;br /&gt;   AND IntVal != 1;&lt;br /&gt;&lt;/pre&gt;I'd never say that my way to write T-SQL is &lt;i&gt;the best&lt;/i&gt;, but you can be sure that all my T-SQL looks like this. It is unimportant if you prefer upper case or lower case keywords like &lt;i&gt;SELECT&lt;/i&gt; but take your decision and comply with it. Take your decision how and what to indent and where to add the commas.&lt;br/&gt;&lt;br/&gt;The worst T-SQL I've seen was most times written by non database developers who "had to do some &lt;b&gt;ugly&lt;/b&gt; T-SQL". T-SQL, like other programming languages, is always as ugly as we write it. (Well, T-SQL provides more features to write bad code than most other languages.) So, it's up to us to write pretty procedures.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Emails&lt;/h3&gt;Emails? Why bother? In my opinion, emails are some kind of comedown of humans writing. In good old days, as we wrote letters with paper we all knew some formatting rules, and we followed them. Today, with emails, many people seem to forgot any kinds of formatting.&lt;br/&gt;&lt;br/&gt;Did you ever get a mail like this?&lt;br/&gt;&lt;blockquote&gt;Subject: todo&lt;br/&gt;Content:&lt;br/&gt;Please implement NewOrder till friday. WE NEED TO GO ONLINE ON MONDAY!!!&lt;br/&gt;thx&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;What does this subject say to me; except "somebody has to do something"? Who is responsible to implement the new feature? I have to look to the email header to see, if I am the only person in the "TO" recipients. If there are even more than one "TO" recipients, the recipients have to guess who is responsible. Why capitalizing the production schedule? Capitalized text always feels like screaming. Does this mean I might have to work on weekend to meet the deadline? Why those three exclamation marks? Does this mean I have to stay on Friday, even if it becomes Saturday, until I'm done? After this hard task assignment a sloppy "thx"? Are you kidding me?&lt;br/&gt;&lt;br/&gt;How about this?&lt;br/&gt;&lt;blockquote&gt;Subject: Feature NewOrder (until Friday)&lt;br/&gt;Content:&lt;br/&gt;Hi Flo&lt;br/&gt;&lt;br/&gt;Please implement the “NewOrder” until next Friday. It's important that we meet the deadline due to a presentation on Monday. Please let me know if you need some additional resources.&lt;br/&gt;&lt;br/&gt;Thanks&lt;br/&gt;John&lt;br/&gt;&lt;/blockquote&gt;Sure, this is much more text to write and read. However, I'm no machine and I don't need (/want) to get my tasks optimized for fast processing (reading). It's a kind of respect to invest some time for assigning a task in a grateful form.&lt;br/&gt;&lt;br/&gt;I don't mean emails to a friend, to ask her for lunch tomorrow. I use to write them sloppy because the content is not really important and I'd probably even speak in slang if I'd stand in front of her.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;I'd really appreciate if more people would feel like an author whenever they are writing. To keep the readers in mind whenever we write is some kind of respect which is always worth.&lt;br/&gt;&lt;br/&gt;Though, sometimes I'd appreciate if &lt;b&gt;&lt;u&gt;I&lt;/u&gt;&lt;/b&gt; would follow this engagement more consequent  than I actually do. However, I know I'm not perfect, I know (at least some of) my personal issues and I'm still working on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-1375751904883391793?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/1375751904883391793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/07/we-are-authors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/1375751904883391793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/1375751904883391793'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/07/we-are-authors.html' title='We Are Authors!'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-7888894534209463512</id><published>2010-07-06T14:40:00.000-07:00</published><updated>2010-07-06T14:40:13.999-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>Table-Valued Parameters</title><content type='html'>This post is initiated by Ken Simmons (&lt;a href="http://cybersql.blogspot.com/"&gt;Blog&lt;/a&gt; | &lt;a href="http://twitter.com/KenSimmons"&gt;Twitter&lt;/a&gt;). He asked to write a blog post that describes our favorite feature of SQL Server. Ken's post &lt;a href="http://cybersql.blogspot.com/2010/07/msdn-ultimate-subscription-contest.html"&gt;here&lt;/a&gt; is not only interesting due to the MSDN package :-) but also caused me thinking about what I changed in my database solutions since SQL Server 2008.&lt;br/&gt;&lt;br/&gt;For sure, this is not my first post about SQL Server 2008 feature User Defined Table-Valued types. I'd not call them as the greatest feature of SQL Server in general, however they are one of the greatest &lt;b&gt;new&lt;/b&gt; features in version 2008.&lt;br/&gt;&lt;br/&gt;&lt;h3&gt;Bulk Load by Ids&lt;/h3&gt;Often it is required to load many rows of one table by their ids or any other attribute. A sample is reloading of already known data.&lt;br/&gt;&lt;br/&gt;One solution is to send one query for each item to be (re-)loaded. However, this causes many small queries, stressing server and network.&lt;br/&gt;&lt;br/&gt;Another approach is to create one dynamic SQL query, containing an IN statement for all ids to be reloaded. Though, this has several issues. Dynamic creation of SQL statements is always a potential open door for SQL injection. Those IN statements make it impossible for SQL Server to reuse existing execution plans. IN statements with many items require many resources on server side and become slow. This works only if there is one unique column to filter.&lt;br/&gt;&lt;br/&gt;The - in my opinion - best solution, before SQL Server 2008, is to create a concatenated string of all IDs to be loaded, send the string to the server, split them into a temp table and use this table joined to the real table to return the requested rows. I wrote a huge post about SQL split functions &lt;a href="http://florianreischl.blogspot.com/2009/09/high-performance-string-split-functions.html"&gt;here&lt;/a&gt;. Though, as cool as this approach is, it stays a little hack. When working with more than one column, this approach becomes awkward since you have to handle hierarchical data (lines and items) within the string.&lt;br/&gt;&lt;br/&gt;User-Defined Table-Valued types are a new and clean way to bulk load rows from database. Let's start with the definition of a new type.&lt;br/&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;CREATE TYPE IntIdTable AS TABLE (&lt;br /&gt;   Id INT NOT NULL PRIMARY KEY CLUSTERED&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;Now, we are able to write a stored procedure which gets this type as parameter. (I don't show the referenced table "TestData100K" because it doesn't really matter. Out of others, it contains one column, called "Id". Please, no bashing for the "SELECT &lt;b&gt;&lt;u&gt;*&lt;/u&gt;&lt;/b&gt;", it's a sample.).&lt;br/&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;CREATE PROCEDURE GetTestDataByIds&lt;br /&gt;   @ids IntIdTable READONLY&lt;br /&gt;AS&lt;br /&gt;   SELECT td.*&lt;br /&gt;   FROM TestData100K td&lt;br /&gt;      JOIN @ids ids ON td.Id = ids.Id;&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;Okay, we're done on server side, let's switch to the client.&lt;br/&gt;First thing we need to be able to address User-Defined Table-Types is a class, implementing the &lt;i&gt;IEnumerable&amp;ltSqlDataRecord&amp;gt;&lt;/i&gt;. (Another way would be a &lt;i&gt;DataTable&lt;/i&gt;, but I don't like this class due to its huge overhead.)&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;class IntRecordEnumerator : IEnumerable&amp;lt;SqlDataRecord&amp;gt; {&lt;br /&gt;   public IntRecordEnumerator(IEnumerable&amp;lt;int&amp;gt; values) {&lt;br /&gt;      _values = values;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   IEnumerable&amp;lt;int&amp;gt; _values;&lt;br /&gt;&lt;br /&gt;   public IEnumerator&amp;lt;SqlDataRecord&amp;gt; GetEnumerator() {&lt;br /&gt;      SqlMetaData metaData = new SqlMetaData("Id", SqlDbType.Int);&lt;br /&gt;&lt;br /&gt;      foreach (int id in _values) {&lt;br /&gt;         SqlDataRecord record = new SqlDataRecord(metaData);&lt;br /&gt;         record.SetInt32(0, id);&lt;br /&gt;         yield return record;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {&lt;br /&gt;      return this.GetEnumerator();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Now, we can use this class as parameter of a &lt;i&gt;SqlParameter&lt;/i&gt;. (Notice, the parameter requires &lt;i&gt;SqlDbType.Structured&lt;/i&gt; and &lt;i&gt;TypeName&lt;/i&gt; to address the name of the table type.)&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;[TestMethod]&lt;br /&gt;public void SearchIds() {&lt;br /&gt;   string sql = "GetTestDataByIds";&lt;br /&gt;   using (SqlConnection connection = CreateOpenConnection())&lt;br /&gt;   using (SqlCommand command = new SqlCommand(sql, connection)) {&lt;br /&gt;      command.CommandType = CommandType.StoredProcedure;&lt;br /&gt;      SqlParameter param = command.Parameters.Add("@Ids", SqlDbType.Structured);&lt;br /&gt;      param.TypeName = "IntIdTable";&lt;br /&gt;&lt;br /&gt;      int[] idsToLoad = new int[] { 1, 2, 3, 4, 5 };&lt;br /&gt;      param.Value = new IntRecordEnumerator(idsToLoad);&lt;br /&gt;&lt;br /&gt;      using (SqlDataReader reader = command.ExecuteReader()) {&lt;br /&gt;         while (reader.Read()) {&lt;br /&gt;            int id = (int)reader["Id"];&lt;br /&gt;            Console.Write(id);&lt;br /&gt;            Assert.IsTrue(idsToLoad.Contains(id));&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;&lt;h3&gt;Streaming Data To The Server&lt;/h3&gt;In distributed systems it is important to synchronize data between different databases.&lt;br/&gt;&lt;br/&gt;If possible to use database features like BCP or SSIS, this is often the best solution. However, sometimes it is required to do some additional work, containing business logic, those solutions require a duplication of business logic into the database. In addition, if there are data to be updated (not only inserted) the data have to be packed into a staging table before they can be handled by a procedure. Staging tables are a nice temporary storage but can become tricky if there are concurrent synchronization jobs.&lt;br/&gt;&lt;br/&gt;The classic and, as far as I know, most common solution today is using single &lt;i&gt;INSERT&lt;/i&gt; statements to load those bulk data row by row. As denoted above, this becomes a little stress test for database server and network.&lt;br/&gt;&lt;br/&gt;Another, a bit esoteric, approach is to use SQL Server 2005's XML functionality to create one huge XML package, containing all data to be written into database server. Problem is XML is a quiet chatty language and causes a huge memory usage on client and server.&lt;br/&gt;&lt;br/&gt;Here, User-Defined Table-Valued types can be used to push all data in one step into a procedure. Business logic can be applied while streaming through all data to be synchronized. The procedure finally updates and inserts the data into their destination table. I first wrote about this approach &lt;a href="http://florianreischl.blogspot.com/2009/11/table-valued-parametes-performance.html"&gt;here&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;Again, we start with a table type.&lt;br/&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;CREATE TYPE ImportSampleTable AS TABLE (&lt;br /&gt;   FirstName VARCHAR(30)&lt;br /&gt;   ,LastName VARCHAR(30)&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;A simple procedure, that gets the type as parameter and inserts the rows into a table.&lt;br/&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;CREATE PROCEDURE ImportSampleFile&lt;br /&gt;   @importData ImportSampleTable READONLY&lt;br /&gt;AS&lt;br /&gt;   INSERT INTO ImportSample&lt;br /&gt;   SELECT *&lt;br /&gt;   FROM @importData;&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;Heating to the client...&lt;br/&gt;An implementation of a &lt;i&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/i&gt;.&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;class FileToLoad : IEnumerable&amp;lt;SqlDataRecord&amp;gt; {&lt;br /&gt;   public FileToLoad(string fileName, SqlConnection connection) {&lt;br /&gt;      _fileName = fileName;&lt;br /&gt;      _connection = connection;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   string _fileName;&lt;br /&gt;   SqlConnection _connection;&lt;br /&gt;   SqlMetaData[] _metaData;&lt;br /&gt;&lt;br /&gt;   public IEnumerator&amp;lt;SqlDataRecord&amp;gt; GetEnumerator() {&lt;br /&gt;      CreateMetaData();&lt;br /&gt;&lt;br /&gt;      using (StreamReader reader = new StreamReader(_fileName)) {&lt;br /&gt;         while (!reader.EndOfStream) {&lt;br /&gt;            SqlDataRecord record = CreateRecord(reader);&lt;br /&gt;            yield return record;&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void CreateMetaData() {&lt;br /&gt;      _metaData = new SqlMetaData[] {&lt;br /&gt;         new SqlMetaData("FirstName", SqlDbType.VarChar, 30),&lt;br /&gt;         new SqlMetaData("LastName", SqlDbType.VarChar, 30),&lt;br /&gt;      };&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private SqlDataRecord CreateRecord(StreamReader reader) {&lt;br /&gt;      string line = reader.ReadLine();&lt;br /&gt;      SqlDataRecord record = new SqlDataRecord(_metaData);&lt;br /&gt;      string[] lineItems = line.Split('\t');&lt;br /&gt;      record.SetString(0, lineItems[0]);&lt;br /&gt;      record.SetString(1, lineItems[1]);&lt;br /&gt;      return record;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {&lt;br /&gt;      return this.GetEnumerator();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;And again, we are ready to use the table valued type as parameter for another test.&lt;br/&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;[TestMethod]&lt;br /&gt;public void StreamingLoad() {&lt;br /&gt;   using (SqlConnection connection = CreateOpenConnection())&lt;br /&gt;   using (SqlCommand command = new SqlCommand("ImportSampleFile", connection)) {&lt;br /&gt;      command.CommandType = CommandType.StoredProcedure;&lt;br /&gt;      SqlParameter param = command.Parameters.Add("@importData", SqlDbType.Structured);&lt;br /&gt;      param.TypeName = "ImportSampleTable";&lt;br /&gt;      // get a sample file&lt;br /&gt;      string fileName = GetType().Assembly.Location;&lt;br /&gt;      fileName = Path.GetDirectoryName(fileName);&lt;br /&gt;      fileName = Path.Combine(fileName, "FileToLoad.txt");&lt;br /&gt;      &lt;br /&gt;      param.Value = new FileToLoad(fileName, connection);&lt;br /&gt;      command.ExecuteNonQuery();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;User-Defined Table-Valued types a nice new feature of SQL Server 2008! I did not find many reasons to use them in plain T-SQL, but they provide a native support of set-based solutions between client and server and this is a really great enhancement of SQL Server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-7888894534209463512?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/7888894534209463512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/07/table-valued-parameters.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7888894534209463512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7888894534209463512'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/07/table-valued-parameters.html' title='Table-Valued Parameters'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-833923588542578073</id><published>2010-06-11T01:52:00.000-07:00</published><updated>2010-06-11T01:58:05.756-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lambda'/><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='web service'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><title type='text'>Centralized Error Handling With Lambda</title><content type='html'>For many reasons it is often useful - and important - to catch exceptions in UI or other boundary classes like web-services. Out of many other the most important reasons are usually security, to avoid to show the information of an internal system error to the client, and traceability, to log the error for investigations.&lt;br /&gt;&lt;br /&gt;The problem is, exception handling is quiet complicated code and is often highly redundant, what makes it awkward to keep it in sync.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Common Approach For Exception Handling&lt;/h3&gt;As a simple sample, guess we are developing a web-service method that returns a Country object from data storage by a specified ISO 3-alpha.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;[OperationContract]&lt;br /&gt;public Country GetByIsoAlpha3_Simple(string alpha3)&lt;br /&gt;{&lt;br /&gt;    Logger.Trace("Entered GetByIsoAlpha3");&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        ThrowHelper.CheckNullArg(alpha3);&lt;br /&gt;        CountrySource source = new CountrySource();&lt;br /&gt;        return source.GetByIsoAlpha3(alpha3);&lt;br /&gt;    }&lt;br /&gt;    catch (ArgumentException ex)&lt;br /&gt;    {&lt;br /&gt;        throw new FaultException(ex.Message);&lt;br /&gt;    }&lt;br /&gt;    catch (DbException ex)&lt;br /&gt;    {&lt;br /&gt;        Logger.LogEx(ex);&lt;br /&gt;        throw new FaultException("There was error with the data storage.");&lt;br /&gt;    }&lt;br /&gt;    catch (Exception ex)&lt;br /&gt;    {&lt;br /&gt;        Logger.LogEx(ex);&lt;br /&gt;        throw new FaultException("A internal error occurred");&lt;br /&gt;    }&lt;br /&gt;    finally&lt;br /&gt;    {&lt;br /&gt;        Logger.Trace("Leaving GetByIsoAlpha3");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As we see, the real functionality is only two lines of code, the rest of the 25 lines are standard exception handling and the validation of the input values.&lt;br /&gt;&lt;br /&gt;The problem with this method is, it's very dangerous remember all required tasks for standard exception handling. Does it handle all standard exceptions we usually handle? Might it be useful to log the &lt;i&gt;ArgumentException&lt;/i&gt;? Do we really want to tell the caller that we had an error with the data storage? How can we ensure that all web methods do the same standard exception handling.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Extract The Exception Handling&lt;/h3&gt;A good way to ensure all &lt;b&gt;standard&lt;/b&gt; exception handling is to move it out into a static helper class.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;static class WsHelper&lt;br /&gt;{&lt;br /&gt;    public static T ExecuteWebMethod&amp;lt;T&amp;gt;(string methodName, Func&amp;lt;T&amp;gt; method)&lt;br /&gt;    {&lt;br /&gt;        Logger.Trace("Entered " + methodName);&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            return method();&lt;br /&gt;        }&lt;br /&gt;        catch (ArgumentException ex)&lt;br /&gt;        {&lt;br /&gt;            throw new FaultException(ex.Message);&lt;br /&gt;        }&lt;br /&gt;        catch (DbException ex)&lt;br /&gt;        {&lt;br /&gt;            Logger.LogEx(ex);&lt;br /&gt;            throw new FaultException("There was error with the data storage.");&lt;br /&gt;        }&lt;br /&gt;        catch (Exception ex)&lt;br /&gt;        {&lt;br /&gt;            Logger.LogEx(ex);&lt;br /&gt;            throw new FaultException("A internal error occurred");&lt;br /&gt;        }&lt;br /&gt;        finally&lt;br /&gt;        {&lt;br /&gt;            Logger.Trace("Leaving " + methodName);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Using Lambda Expressions To Utilize The Helper&lt;/h3&gt;Now, we can utilize the &lt;i&gt;ExecuteWebMethod&lt;/i&gt; method with a simple Lambda expression.&lt;pre class="brush: csharp;"&gt;&lt;br /&gt;[OperationContract]&lt;br /&gt;public Country GetByIsoAlpha3_Lambda(string alpha3)&lt;br /&gt;{&lt;br /&gt;    return WsHelper.ExecuteWebMethod("GetByIsoAlpha3_Lambda", () =&amp;gt;&lt;br /&gt;    {&lt;br /&gt;        ThrowHelper.CheckNullArg(alpha3);&lt;br /&gt;        CountrySource source = new CountrySource();&lt;br /&gt;        return source.GetByIsoAlpha3(alpha3);&lt;br /&gt;    });&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;As we see, the code of our web method is reduced to six lines. Still three lines for our method specific work, two lines with braces and one line calling the helper method which gets a &lt;i&gt;Func&amp;lt;T&amp;gt;&lt;/i&gt; that represents the implementation of the web method.&lt;br/&gt;&lt;h3&gt;Possible Extensions&lt;/h3&gt;The exceptions handled in this sample are only exemplary. If you have some other common standard exceptions like a &lt;i&gt;ValidationException&lt;/i&gt; or a general &lt;i&gt;BusinessException&lt;/i&gt;, feel free to extend the &lt;i&gt;ExecuteWebMethod&lt;/i&gt;.&lt;br/&gt;For sure, you noticed the &lt;i&gt;methodName&lt;/i&gt; parameter, provided for the &lt;i&gt;ExecuteWebMethod&lt;/i&gt; operation. To get rid of this parameter we can use the &lt;a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx"&gt;StackTrace&lt;/a&gt; class to determine the calling method. In case of web services or other boundaries, this is a good approach. Nevertheless, be careful with &lt;i&gt;StackTrace&lt;/i&gt; in highly utilized methods since stack trace evaluation is an expensive task.&lt;h3&gt;Restrictions&lt;/h3&gt;The helper method should be &lt;b&gt;only&lt;/b&gt; responsible for standard exception handling. Don't try to move all use case specific exception handling into the external helper method.&lt;h3&gt;Conclusion&lt;/h3&gt;Lambda is generally a powerful feature to inject standard method with external functionality. This blog post showed only one out of many solutions to &lt;a href="http://en.wikipedia.org/wiki/Decorator_pattern"&gt;decorate&lt;/a&gt; a specific implementation with other functionalities.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-833923588542578073?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/833923588542578073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/06/centralized-error-handling-with-lambda.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/833923588542578073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/833923588542578073'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/06/centralized-error-handling-with-lambda.html' title='Centralized Error Handling With Lambda'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-4352619664335484639</id><published>2010-05-30T05:02:00.000-07:00</published><updated>2010-06-05T07:37:42.396-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='serialization'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Streaming Serialization with XmlSerializer</title><content type='html'>&lt;span class="text"&gt;As known, .NET provides several different ways to serialize and de-serialize objects. One of those serialization techniques is the &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx"&gt;XmlSerializer&lt;/a&gt; class. Generally this class provides a nice, straight forward approach. However, there is one problem with this (and most other) serialization classes, it does not support streaming. If you want to (de-)serialize really large counts of objects, you might be run into physical memory problems.&lt;br/&gt;&lt;br/&gt;One solution is to implement the &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx"&gt;IXmlSerializable&lt;/a&gt; interface, which exposes the &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.readxml.aspx"&gt;ReadXml(XmlReader)&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.writexml.aspx"&gt;WriteXml(XmlWriter)&lt;/a&gt; operations. Though, this ends in quiet a bunch of complicated code.&lt;br/&gt;&lt;br/&gt;To handle the memory problem when using the XmlSerializer class, here you can find two simple wrapper classes which provide a streaming functionality.&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;h3&gt;XmlStreamingSerializer&lt;/h3&gt;&lt;span class="text"&gt;The XmlStreamingSerializer creates an internal instance of a XmlSerializer and a XmlWriter which provides the persistence management. To avoid the "xsi" and "xsd" namespaces again and again for each object to be serialized, it simply provides an empty &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializernamespaces.aspx"&gt;XmlSerializerNamespaces&lt;/a&gt;. I found that trick in one of the comments on &lt;a href="http://www.hanselman.com/blog/"&gt;Scott Hanselman's&lt;/a&gt; blog about &lt;a href="http://www.hanselman.com/blog/XmlFragmentWriterOmitingTheXmlDeclarationAndTheXSDAndXSINamespaces.aspx"&gt;XmlFragmentWriter&lt;/a&gt;.&lt;/span&gt;&lt;pre class="brush: csharp;"&gt;public class XmlStreamingSerializer&amp;lt;T&amp;gt; {&lt;br /&gt;   // ------------------------------------------------------------------&lt;br /&gt;   static XmlStreamingSerializer() {&lt;br /&gt;      _ns = new XmlSerializerNamespaces();&lt;br /&gt;      _ns.Add("", "");&lt;br /&gt;   }&lt;br /&gt;   // ------------------------------------------------------------------&lt;br /&gt;   private XmlStreamingSerializer() {&lt;br /&gt;      _serializer = new XmlSerializer(typeof(T));&lt;br /&gt;   }&lt;br /&gt;   // ------------------------------------------------------------------&lt;br /&gt;   public XmlStreamingSerializer(TextWriter w)&lt;br /&gt;      : this(XmlWriter.Create(w)) {&lt;br /&gt;   }&lt;br /&gt;   // ------------------------------------------------------------------&lt;br /&gt;   public XmlStreamingSerializer(XmlWriter writer) : this() {&lt;br /&gt;      _writer = writer;&lt;br /&gt;      _writer.WriteStartDocument();&lt;br /&gt;      _writer.WriteStartElement("ArrayOf" + typeof(T).Name);&lt;br /&gt;   }&lt;br /&gt;   // ==================================================================&lt;br /&gt;   static XmlSerializerNamespaces _ns;&lt;br /&gt;   XmlSerializer _serializer = new XmlSerializer(typeof(T));&lt;br /&gt;   XmlWriter _writer;&lt;br /&gt;   bool _finished;&lt;br /&gt;   // ==================================================================&lt;br /&gt;   public void Finish() {&lt;br /&gt;      _writer.WriteEndDocument();&lt;br /&gt;      _writer.Flush();&lt;br /&gt;      _finished = true;&lt;br /&gt;   }&lt;br /&gt;   // ------------------------------------------------------------------&lt;br /&gt;   public void Close() {&lt;br /&gt;      if (!_finished)&lt;br /&gt;         Finish();&lt;br /&gt;      _writer.Close();&lt;br /&gt;   }&lt;br /&gt;   // ------------------------------------------------------------------&lt;br /&gt;   public void Serialize(T item) {&lt;br /&gt;      _serializer.Serialize(_writer, item, _ns);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;&lt;h3&gt;XmlStreamingDeserializer&lt;/h3&gt;&lt;span class="text"&gt;As the serializer, the XmlStreamingDeserializer class wraps an instance of a .NET XmlSerializer. It uses a XmlReader to provide the streaming functionality and utilizes the &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.readsubtree.aspx"&gt;XmlReader.ReadSubtree&lt;/a&gt; method to get the current serialized item into the XmlSerializer.&lt;/span&gt;&lt;pre class="brush: csharp;"&gt;public class XmlStreamingDeserializer&amp;lt;T&amp;gt; {&lt;br /&gt;   // ------------------------------------------------------------------&lt;br /&gt;   static XmlStreamingDeserializer() {&lt;br /&gt;      _ns = new XmlSerializerNamespaces();&lt;br /&gt;      _ns.Add("", "");&lt;br /&gt;   }&lt;br /&gt;   // ------------------------------------------------------------------&lt;br /&gt;   private XmlStreamingDeserializer() {&lt;br /&gt;      _serializer = new XmlSerializer(typeof(T));&lt;br /&gt;   }&lt;br /&gt;   public XmlStreamingDeserializer(TextReader reader)&lt;br /&gt;      : this(XmlReader.Create(reader)) {&lt;br /&gt;   }&lt;br /&gt;   public XmlStreamingDeserializer(XmlReader reader) : this() {&lt;br /&gt;      _reader = reader;&lt;br /&gt;   }&lt;br /&gt;   // ==================================================================&lt;br /&gt;   static XmlSerializerNamespaces _ns;&lt;br /&gt;   XmlSerializer _serializer = new XmlSerializer(typeof(T));&lt;br /&gt;   XmlReader _reader;&lt;br /&gt;   // ==================================================================&lt;br /&gt;   public void Close() {&lt;br /&gt;      _reader.Close();&lt;br /&gt;   }&lt;br /&gt;   // ------------------------------------------------------------------&lt;br /&gt;   public T Deserialize() {&lt;br /&gt;      while (_reader.Read()) {&lt;br /&gt;         if (_reader.NodeType == XmlNodeType.Element&lt;br /&gt;               &amp;amp;&amp;amp; _reader.Depth == 1&lt;br /&gt;               &amp;amp;&amp;amp; _reader.Name == typeof(T).Name) {&lt;br /&gt;            XmlReader reader = _reader.ReadSubtree();&lt;br /&gt;            return (T)_serializer.Deserialize(reader);&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;      return default(T);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;Some Tests&lt;/h3&gt;&lt;span class="text"&gt;Here you can find some performance test results.&lt;br/&gt;&lt;br/&gt;I serialized a very simple object structure shown below.&lt;/span&gt;&lt;pre class="brush: csharp;"&gt;public class Foo {&lt;br /&gt;   [XmlAttribute]&lt;br /&gt;   public int Id { get; set; }&lt;br /&gt;   [XmlAttribute]&lt;br /&gt;   public string Bar { get; set; }&lt;br /&gt;   public List&amp;lt;foo&amp;gt; SubFoos { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span class="text"&gt;I serialized 10,000 instances, each with 100 sub items. Maybe you don't have to serialize so many objects, but the depth of serialized objects is often far deeper than two levels.&lt;/span&gt;&lt;table class="results_table" cellspacing="0px"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Action&lt;/th&gt;&lt;th&gt;Duration (ms)&lt;/th&gt;&lt;th&gt;RAM (MB)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Serialization with XmlSerializer&lt;/td&gt;&lt;td&gt;2954&lt;/td&gt;&lt;td&gt;134&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Serialization with XmlStreamingSerializer&lt;/td&gt;&lt;td&gt;2391&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;De-serialization with XmlSerializer&lt;/td&gt;&lt;td&gt;3662&lt;/td&gt;&lt;td&gt;150&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;De-serialization with XmlStreamingDeserializer&lt;/td&gt;&lt;td&gt;2953&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;span class="text"&gt;Those test results are not representative for any purpose. Especially the apparently faster processing of the streaming classes seems to be a bit curious to me. Nevertheless, the more important factor in this test results it the far less memory requirement (about 10% here).&lt;/span&gt;&lt;h3&gt;Possible Extensions&lt;/h3&gt;&lt;span class="text"&gt;Both classes, shown above are quiet simple and there are several possible extensions to get them more powerful.&lt;ul&gt;&lt;li&gt;&lt;b&gt;One class for both.&lt;/b&gt; If you prefer one serialization class for serialization and de-serialization, feel free to merge both into one. I preferred the two-class solution to keep each of them more pure.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Configurable document element name.&lt;/b&gt; Since now, the serializer creates a hard-coded document element name called "&lt;b&gt;ArrayOf&lt;/b&gt;MyType". This behavior matches to the XmlSerializer behavior, when serializing an IEnumerable&amp;lt;out T&amp;gt;. Feel free make this &lt;/li&gt;&lt;li&gt;&lt;b&gt;Xml Namespaces.&lt;/b&gt; The above serialization classes doe not support XML namespaces. If you need namespaces just add something like a public XmlSerializerNamespaces property.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Different objects.&lt;/b&gt; XML files often contain more than one type of objects. Support of different object types could easily be added by a dictionary of serializers.&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;span class="text"&gt;The intension of this blog was not to present a fully dressed streaming XML framework. I tried to a prove of concept for how to handle large amounts of objects in combination with the .NET XmlSerializer class.&lt;/span&gt;&lt;h3&gt;Attachments&lt;/h3&gt;&lt;span class="text"&gt;Here you can find the XmlStreamingSerializer and XmlStreamingDeserializer classes as well as a simple console application I used for my tests.&lt;ul&gt;&lt;li&gt;&lt;a href="http://sites.google.com/site/florianreischl/blogspot-files/XmlStreamingSerializer.cs?attredirects=0&amp;d=1"&gt;XmlStreamingSerializer.cs&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sites.google.com/site/florianreischl/blogspot-files/XmlStreamingDeserializer.cs?attredirects=0&amp;d=1"&gt;XmlStreamingDeserializer.cs&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sites.google.com/site/florianreischl/blogspot-files/TestXmlStreamingSerialization.cs?attredirects=0&amp;d=1"&gt;TestXmlStreamingSerialization.cs&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-4352619664335484639?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/4352619664335484639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/05/streaming-serialization-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/4352619664335484639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/4352619664335484639'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/05/streaming-serialization-with.html' title='Streaming Serialization with XmlSerializer'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-2325630206143187332</id><published>2010-05-14T06:14:00.000-07:00</published><updated>2010-06-05T07:56:58.274-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Layers, Bondaries And How To Exchange Data</title><content type='html'>One of the most popular (architecual) patterns is the &lt;b&gt;Three-Layer&lt;/b&gt; design. Unfortunately, this pattern is often convounded with the three-tier pattern. I take the definition of authors like &lt;a href="http://www.martinfowler.com"&gt;Martin Fowler&lt;/a&gt;, &lt;a href="http://www.thomaserl.com"&gt;Thomas Erl&lt;/a&gt; and &lt;a href="http://www.craiglarman.com"&gt;Craig Larman&lt;/a&gt;, which says:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The &lt;b&gt;Three-Tier&lt;/b&gt; pattern describes a software deployment into three physical tiers. A common solution for this pattern is a database server, a web server and a web client (browser)&lt;/li&gt;&lt;li&gt;The &lt;b&gt;Three-Layer&lt;/b&gt; pattern describes how to split sofware concerns into three different layers. These layers are a data acess layer, a business logic layer and a presentation layer. The layers might also be deployed into different tiers, though, this is optional.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The below picture shows the three layers and their positions.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_hBTxNhEL4oY/S-rQfsCSeaI/AAAAAAAAAFk/pwLU41QEKkU/s1600/three_layer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="295" src="http://1.bp.blogspot.com/_hBTxNhEL4oY/S-rQfsCSeaI/AAAAAAAAAFk/pwLU41QEKkU/s400/three_layer.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The intention of this blog is not to describe how to implement the &lt;b&gt;Three-Layer&lt;/b&gt; pattern, there are already milions of web resources which does this. This blog focuses on the data exchange between the data access layer (DAL) and the business logic layer (BLL).&lt;br /&gt;&lt;h3&gt;The Architectual Challange&lt;/h3&gt;Most sources, describing the three-layer pattern, advice to separate the DAL and the BLL into two different assemblies. The reason is to avoid mixing different concerns, what is a good thing. This brings up an intersting issue. How to create BLL objects (like Customer or Order) from DAL?&lt;br /&gt;&lt;br /&gt;Why? Because each layer should only communicate with the layer directly below. A layer should never communicate with a above layer. So, the BLL communicates with the DAL, but the DAL never (active) communicates with the BLL. However, the business objects (aka. entities, domain objects, ...) are stored within the BLL, so how to create objects which are not known within the DAL?&lt;br /&gt;&lt;br /&gt;The following topics describe diferent solutions of how to get data from DAL into BLL and back.&lt;br /&gt;&lt;h3&gt;DataTables&lt;/h3&gt;DataTables are one option to transport data from DAL to the BLL. The DAL gets the data from data store, transforms the data into a DataTable and returns the table to the calling BLL. The BLL gets the DataTable and transforms the data into business objects. For saving changes, the BLL transforms the business objects into a DataTable and calls a distinct save method from DAL.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;advantages&lt;/b&gt; of DataTable objects are, they support other rich features like complex sorting, searching and data binding. They are serializable and can be used for data exchange over network.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;disadvantages&lt;/b&gt; are, DataTables (especially if not using typed DataSets) the contained data are not guaranteed to be valid by type. Another issue of DataTables is the overhead, since DataTables objects are very rich objects. Last but not least, this approach requires a huge effort of quiet simple mapping code (= unhappy developer) within the BLL from a DataTable into business objects and back into a DataTable.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;// ====================================================================&lt;br /&gt;// DAL&lt;br /&gt;public DataTable GetCustomers(object criteria) {&lt;br /&gt;   using (IDataReader reader = CreateReader(criteria)) {&lt;br /&gt;      // create results DataTable&lt;br /&gt;      DataTable result = new DataTable();&lt;br /&gt;      result.Columns.Add("Id", typeof(int));&lt;br /&gt;      result.Columns.Add("Name", typeof(string));&lt;br /&gt;      // fill the table&lt;br /&gt;      while (reader.Read()) {&lt;br /&gt;         DataRow row = result.NewRow();&lt;br /&gt;         row["Id"] = reader["Id"];&lt;br /&gt;         row["Name"] = reader["Name"];&lt;br /&gt;         result.Rows.Add(row);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      return result;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;public void SaveCustomers(DataTable data) { /* do save*/ }&lt;br /&gt;// ====================================================================&lt;br /&gt;// BLL&lt;br /&gt;public void DoFoo() {&lt;br /&gt;   // get the DataTable from DAL&lt;br /&gt;   DataTable data = DAL.GetCustomers(null);&lt;br /&gt;   // convert the DataTable into business objects&lt;br /&gt;   IList&amp;lt;Customer&amp;gt; customers = ConvertDataTable(data);&lt;br /&gt;   // --------------------------------------------&lt;br /&gt;   // do business staff&lt;br /&gt;   // --------------------------------------------&lt;br /&gt;   // convert the business objects into a DataTable to return to DAL&lt;br /&gt;   data = ConvertCustomers(customers);&lt;br /&gt;   DAL.SaveCustomers(data);&lt;br /&gt;}&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;private IList&amp;lt;Customer&amp;gt; ConvertDataTable(DataTable data) {&lt;br /&gt;   // convert DataTable into business objects&lt;br /&gt;   List&amp;lt;Customer&amp;gt; customers = new List&amp;lt;Customer&amp;gt;();&lt;br /&gt;   foreach (var row in data.AsEnumerable()) {&lt;br /&gt;      Customer cust = new Customer();&lt;br /&gt;      cust.Id = (int)row["Id"];&lt;br /&gt;      cust.Name = (string)row["Name"];&lt;br /&gt;      customers.Add(cust);&lt;br /&gt;   }&lt;br /&gt;   return customers;&lt;br /&gt;}&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;private DataTable ConvertCustomers(IEnumerable&amp;lt;Customer&amp;gt; customers) {&lt;br /&gt;   // convert business objects into DataTable&lt;br /&gt;   DataTable data = new DataTable();&lt;br /&gt;   data.Columns.Add("Id", typeof(int));&lt;br /&gt;   data.Columns.Add("Name", typeof(string));&lt;br /&gt;   foreach (var cust in customers) {&lt;br /&gt;      DataRow row = data.NewRow();&lt;br /&gt;      row["Id"] = cust.Id;&lt;br /&gt;      row["Name"] = cust.Name;&lt;br /&gt;      data.Rows.Add(row);&lt;br /&gt;   }&lt;br /&gt;   return data;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Reflection&lt;/h3&gt;Another way to skin the cat is to use .NET (or Java) Reflection features to automate the mapping. The DAL gets the business object types from meta data (like a config file) and handles all the business object creation and field mapping dynamically.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;advantage&lt;/b&gt; of using reflection is, there is very less code to be written and it can be reused for many projects.&lt;br /&gt;&lt;br /&gt;A &lt;b&gt;disadvantage&lt;/b&gt; of reflection is bad runtime performance. Customizations, like differences between data source and business object structures are very difficult to be implemented and error investigations become awkward.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;// ====================================================================&lt;br /&gt;// DAL&lt;br /&gt;// the type of the destination business object (usually, from config)&lt;br /&gt;private Type EntityType { get { return typeof(Customer); } }&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;public IList GetCustomers(object criteria) {&lt;br /&gt;   List&amp;lt;object&amp;gt; result = new List&amp;lt;object&amp;gt;();&lt;br /&gt;   using (IDataReader reader = CreateReader(criteria)) {&lt;br /&gt;      while (reader.Read()) {&lt;br /&gt;         // get empty constructor&lt;br /&gt;         object entity = EntityType.GetConstructor(Type.EmptyTypes).Invoke(new object[0]);&lt;br /&gt;         // fill all DB data into object properties (with same name)&lt;br /&gt;         for (int i = 0; i &amp;lt; reader.FieldCount; i++) {&lt;br /&gt;            string name = reader.GetName(i);&lt;br /&gt;            PropertyInfo prop = EntityType.GetProperty(name);&lt;br /&gt;            prop.SetValue(entity, reader.GetValue(i), null);&lt;br /&gt;         }&lt;br /&gt;         result.Add(entity);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;   return result;&lt;br /&gt;}&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;public void SaveCustomers(IList data) { /* do save*/ }&lt;br /&gt;// ====================================================================&lt;br /&gt;// BLL&lt;br /&gt;public void DoFoo() {&lt;br /&gt;   // get result from DAL&lt;br /&gt;   IList untyped = DAL.GetCustomers(null);&lt;br /&gt;   // convert into typed list&lt;br /&gt;   List&amp;lt;Customer&amp;gt; customers = untyped.Cast&amp;lt;Customer&amp;gt;().ToList();&lt;br /&gt;   // --------------------------------------------&lt;br /&gt;   // do business staff&lt;br /&gt;   // --------------------------------------------&lt;br /&gt;   DAL.SaveCustomers(customers);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Data Transfer Objects&lt;/h3&gt;&lt;a href="http://en.wikipedia.org/wiki/Data_transfer_object"&gt;Data Transfer Objects&lt;/a&gt; (DTOs) are a very clean and type safe solution for data exchange between the layers. They are usually defined within the DAL, will be filled there and mapped into the destination business objects in the BLL.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;advantages&lt;/b&gt; of DTOs are the strong typing and a a good maintainibility. Any kind of mapping customizations are simple to be done.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;disadvantage&lt;/b&gt; is the huge amount of simple mapping code (= unhappy developer) within the BLL to convert received DTOs into business objects and back into DTOs for saving concerns. The best solution to avoid writing all the mapping code is using some kind of souce code generation like a &lt;a href="http://en.wikipedia.org/wiki/CASE_tool#CASE_tools"&gt;CASE&lt;/a&gt; tool.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;// ====================================================================&lt;br /&gt;// DAL&lt;br /&gt;// a customer DTO object for data exchange&lt;br /&gt;public class CustomerDTO {&lt;br /&gt;   public int Id { get; set; }&lt;br /&gt;   public string Name { get; set; }&lt;br /&gt;}&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;public IList&amp;lt;CustomerDTO&amp;gt; GetCustomers(object criteria) {&lt;br /&gt;   // create list of DTOs to exchange result data&lt;br /&gt;   IList&amp;lt;CustomerDTO&amp;gt; result = new List&amp;lt;CustomerDTO&amp;gt;();&lt;br /&gt;   using (IDataReader reader = CreateReader(criteria)) {&lt;br /&gt;      while (reader.Read()) {&lt;br /&gt;         // create DTOs&lt;br /&gt;         CustomerDTO dto = new CustomerDTO();&lt;br /&gt;         dto.Id = (int)reader["Id"];&lt;br /&gt;         dto.Name = (string)reader["Name"];&lt;br /&gt;         result.Add(dto);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;   return result;&lt;br /&gt;}&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;public void SaveCustomers(IEnumerable&amp;lt;CustomerDTO&amp;gt; dtos) { /* do save*/ }&lt;br /&gt;// ====================================================================&lt;br /&gt;// BLL&lt;br /&gt;public void DoFoo() {&lt;br /&gt;   // get DTOs&lt;br /&gt;   IList&amp;lt;CustomerDTO&amp;gt; dtos = DAL.GetCustomers(null);&lt;br /&gt;   // convert into business objects&lt;br /&gt;   IList&amp;lt;Customer&amp;gt; customers = ConvertDTOs(dtos);&lt;br /&gt;   // --------------------------------------------&lt;br /&gt;   // do business staff&lt;br /&gt;   // --------------------------------------------&lt;br /&gt;   // convert back into DTOs to exchange with DAL&lt;br /&gt;   dtos = ConvertCustomers(customers);&lt;br /&gt;   DAL.SaveCustomers(dtos);&lt;br /&gt;}&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;private IList&amp;lt;Customer&amp;gt; ConvertDTOs(IList&amp;lt;CustomerDTO&amp;gt; dtos) {&lt;br /&gt;   // convert DTOs into business objects&lt;br /&gt;   List&amp;lt;Customer&amp;gt; customers = new List&amp;lt;Customer&amp;gt;();&lt;br /&gt;   foreach (var dto in dtos) {&lt;br /&gt;      Customer cust = new Customer();&lt;br /&gt;      cust.Id = dto.Id;&lt;br /&gt;      cust.Name = dto.Name;&lt;br /&gt;      customers.Add(cust);&lt;br /&gt;   }&lt;br /&gt;   return customers;&lt;br /&gt;}&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;private IList&amp;lt;CustomerDTO&amp;gt; ConvertCustomers(IEnumerable&amp;lt;Customer&amp;gt; customers) {&lt;br /&gt;   // convert business objects into DTOs&lt;br /&gt;   IList&amp;lt;CustomerDTO&amp;gt; dtos = new List&amp;lt;CustomerDTO&amp;gt;();&lt;br /&gt;   foreach (var cust in customers) {&lt;br /&gt;      CustomerDTO dto = new CustomerDTO();&lt;br /&gt;      dto.Id = cust.Id;&lt;br /&gt;      dto.Name = cust.Name;&lt;br /&gt;      dtos.Add(dto);&lt;br /&gt;   }&lt;br /&gt;   return dtos;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Interfaces as DTOs&lt;/h3&gt;A last solution (which is my personal favorite) is to create an additional assembly (usually called Project.Core.dll) which contains only the interfaces that describe the business objects data properties. This library is references from both layers, DAL and BLL. It enables the DAL to assign all data directly to the destination objects, that are implemented within the BLL. To create new instances of objects you can use either any kind of &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection"&gt;Dependency Injection (DI)&lt;/a&gt; framework like the Unity application block from &lt;a href="http://entlib.codeplex.com/"&gt;Microsoft Enterprise Library (MEL)&lt;/a&gt; or something like an &lt;i&gt;IFactory&amp;lt;T&amp;gt;&lt;/i&gt; interface, defined in the Core library, which is used as an &lt;a href="http://en.wikipedia.org/wiki/Abstract_factory_pattern"&gt;Abstract Factory&lt;/a&gt; and implemented within the BLL. To inject the DAL with the abstract factory, you can use DI or static code.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;advantages&lt;/b&gt; of this approach are all the advantages of DTOs. In addition there is way less source code to be written, since no additional mapping into business objects is needed; the DTOs are covered by the interfaces, which are realized by the business objects.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;disadvantages&lt;/b&gt; of this solution is the additional library, conaining the interfaces and an additional architectual complexity due to the DI framework and/or the factory class(es).&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;// ====================================================================&lt;br /&gt;// Core library&lt;br /&gt;// interface for Customer to exchange data&lt;br /&gt;public interface ICustomer {&lt;br /&gt;   int Id { get; set; }&lt;br /&gt;   string Name { get; set; }&lt;br /&gt;}&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;// factory interface to create new business objects from DAL&lt;br /&gt;public interface IFactory&amp;lt;T&amp;gt; {&lt;br /&gt;   T Create();&lt;br /&gt;}&lt;br /&gt;// ====================================================================&lt;br /&gt;// DAL&lt;br /&gt;public class CustomerMapper&amp;lt;T&amp;gt; : SamplesMapperBase&lt;br /&gt;    where T : ICustomer {&lt;br /&gt;   // the factory; injected at runtime by BLL or any kind of DI&lt;br /&gt;   public IFactory&amp;lt;T&amp;gt; Factory { get; set; }&lt;br /&gt;&lt;br /&gt;   public IList&amp;lt;T&amp;gt; GetCustomers(object criteria) {&lt;br /&gt;      IList&amp;lt;T&amp;gt; result = new List&amp;lt;T&amp;gt;();&lt;br /&gt;      using (IDataReader reader = CreateReader(criteria)) {&lt;br /&gt;         while (reader.Read()) {&lt;br /&gt;            // create business object instance from factory&lt;br /&gt;            T customer = Factory.Create();&lt;br /&gt;            customer.Id = (int)reader["Id"];&lt;br /&gt;            customer.Name = (string)reader["Name"];&lt;br /&gt;            result.Add(customer);&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;      return result;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void SaveCustomers(IList&amp;lt;T&amp;gt; data) { /* do save*/ }&lt;br /&gt;}&lt;br /&gt;// ====================================================================&lt;br /&gt;// BLL&lt;br /&gt;// simple sample implementation for customer factory&lt;br /&gt;class CustomerFactory : IFactory&amp;lt;Customer&amp;gt; {&lt;br /&gt;   public Customer Create() {&lt;br /&gt;      return new Customer();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;// instance of customer mapper. The generic parameter specifies the&lt;br /&gt;// business objects type&lt;br /&gt;public CustomerMapper&amp;lt;Customer&amp;gt; DAL { get; set; }&lt;br /&gt;// --------------------------------------------------------------------&lt;br /&gt;public void DoFoo() {&lt;br /&gt;   // directly get the business objects from DAL&lt;br /&gt;   IList&amp;lt;Customer&amp;gt; customers = DAL.GetCustomers(null);&lt;br /&gt;   // --------------------------------------------&lt;br /&gt;   // do business staff&lt;br /&gt;   // --------------------------------------------&lt;br /&gt;   DAL.SaveCustomers(customers);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Other Solutions&lt;/h3&gt;There might be myriad of other solutions to exchange data between those both layers, like XML or untyped Object-Arrays, though, in this blog I tried to show the (in my opinion) most popular and efficient.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&amp;lt;off topic&amp;gt;Long time ago since last blog... It's good to find some time for writing.&amp;lt;/off topic&amp;gt;&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-2325630206143187332?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/2325630206143187332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/05/layers-bondaries-and-how-to-exchange.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/2325630206143187332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/2325630206143187332'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/05/layers-bondaries-and-how-to-exchange.html' title='Layers, Bondaries And How To Exchange Data'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_hBTxNhEL4oY/S-rQfsCSeaI/AAAAAAAAAFk/pwLU41QEKkU/s72-c/three_layer.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-8425026424078791666</id><published>2010-02-01T12:43:00.000-08:00</published><updated>2010-02-01T12:43:37.025-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><title type='text'>Assert Helper Class</title><content type='html'>Today I'll share one of my simple but handy helper classes. Unit testing frameworks like Visual Studio Unit Tests or NUnit usually provide a validation class usually called "&lt;i&gt;Assert&lt;/i&gt;" that provides a large set of static methods for test result validation. Without those frameworks the standard .NET way for runtime validation in debug sessions is &lt;a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.debug.assert.aspx"&gt;System.Diagnostics.Debug.Asser(bool)&lt;/a&gt; method. Generally, this method works fine, but I prefer the more handy methods of unit testing frameworks like &lt;i&gt;AreEqual(arg1, arg2)&lt;/i&gt; or &lt;i&gt;IsNotNull(arg)&lt;/i&gt;. Therefore, I created a simple static helper class called &lt;i&gt;Assert&lt;/i&gt; which covers most of those test framework methods.&lt;br /&gt;&lt;br /&gt;The class does nothing special, it just maps the standard &lt;i&gt;Debug.Assert&lt;/i&gt; and &lt;i&gt;Debug.Fail&lt;/i&gt; methods to a more sophisticated interface. Like .NET &lt;i&gt;Debug.Assert&lt;/i&gt; method, all methods of the class are marked with &lt;a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.conditionalattribute.aspx"&gt;System.Diagnostics.ConditionalAttribute&lt;/a&gt; and condition "DEBUG". So all method calls in project code become removed when compiling in "Release Mode".&lt;br /&gt;&lt;br /&gt;Here's a little sample which shows how to use the class compared with &lt;i&gt;Debug.Assert&lt;/i&gt; method.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;// input parameter validation in private methods&lt;br /&gt;Assert.NullArg(someParam, "someParam");&lt;br /&gt;Debug.Assert(someParam != null, "someParam cannot be null");&lt;br /&gt;&lt;br /&gt;// not null validation&lt;br /&gt;List&amp;lt;int&amp;gt; list = new List&amp;lt;int&amp;gt;();&lt;br /&gt;Assert.IsNotNull(list);&lt;br /&gt;Debug.Assert(list != null);&lt;br /&gt;&lt;br /&gt;// null validation&lt;br /&gt;object nullValue = null;&lt;br /&gt;Assert.IsNull(nullValue);&lt;br /&gt;Debug.Assert(nullValue == null);&lt;br /&gt;&lt;br /&gt;// equality validation of reference types (which usually&lt;br /&gt;// don't overwrite the "==" operator)&lt;br /&gt;string s1 = "foo", s2 = "foo";&lt;br /&gt;Assert.AreEqual(s1, s2);&lt;br /&gt;Debug.Assert(&lt;br /&gt;   (s1 == null &amp;amp;&amp;amp; s2 == null)&lt;br /&gt;   || (s1 != null &amp;amp;&amp;amp; s1.Equals(s2))&lt;br /&gt;   );&lt;br /&gt;&lt;br /&gt;// type validation&lt;br /&gt;object o1 = "foo";&lt;br /&gt;Assert.IsOfType(o1, typeof(string));&lt;br /&gt;Debug.Assert(&lt;br /&gt;   o1 != null &lt;br /&gt;   &amp;amp;&amp;amp; typeof(string).IsAssignableFrom(o1.GetType()));&lt;br /&gt;&lt;br /&gt;// not equal validation with error text&lt;br /&gt;int num1 = 1, num2 = 2;&lt;br /&gt;Assert.AreNotEqual(num1, num2, "{0} cannot be {1}", num1, num2);&lt;br /&gt;Debug.Assert(num1 != num2,&lt;br /&gt;             string.Format("{0} cannot be {1}", num1, num2));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And here's the complete code of the class.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;using System;&lt;br /&gt;using System.Diagnostics;&lt;br /&gt;using System.Globalization;&lt;br /&gt;&lt;br /&gt;namespace ClassLibrary1.Diagnostics {&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Helper class for debug assertions.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;remarks&amp;gt;&lt;br /&gt;   /// This class represents a wrapper of &lt;br /&gt;   /// &amp;lt;see cref="System.Diagnostics.Debug"/&amp;gt; class which provides a &lt;br /&gt;   /// richer interface and enables a simplified debug assertion.&lt;br /&gt;   /// &amp;lt;p/&amp;gt;&lt;br /&gt;   /// All methods are marked with &lt;br /&gt;   /// &amp;lt;see cref="System.Diagnostics.ConditionalAttribute"/&amp;gt; with &lt;br /&gt;   /// "DEBUG" condition string. This causes the method calls to be &lt;br /&gt;   /// removed from production source code when compiling in "Release" &lt;br /&gt;   /// mode.&lt;br /&gt;   /// &amp;lt;/remarks&amp;gt;&lt;br /&gt;   public static class Assert {&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts two specified argiments to be equal to each other.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg1"&amp;gt;The first argument to be compared for &lt;br /&gt;      /// equality.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg2"&amp;gt;The first argument to be compared for &lt;br /&gt;      /// equality.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void AreEqual(object arg1, object arg2) {&lt;br /&gt;         if (arg1 == null &amp;amp;&amp;amp; arg2 == null)&lt;br /&gt;            return;&lt;br /&gt;         if (arg1 == null)&lt;br /&gt;            Debug.Assert(false);&lt;br /&gt;         Debug.Assert(arg1.Equals(arg2));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts two specified argiments to be equal to each other.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg1"&amp;gt;The first argument to be compared for &lt;br /&gt;      /// equality.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg2"&amp;gt;The first argument to be compared for &lt;br /&gt;      /// equality.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void AreEqual(object arg1, object arg2, string message, &lt;br /&gt;                                  params object[] args) {&lt;br /&gt;         if (arg1 == null &amp;amp;&amp;amp; arg2 == null)&lt;br /&gt;            return;&lt;br /&gt;         if (arg1 == null)&lt;br /&gt;            Debug.Assert(false, GetMessage(message, args));&lt;br /&gt;         Debug.Assert(arg1.Equals(arg2), GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts two specified argiments to be equal to each other.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg1"&amp;gt;The first argument to be compared for &lt;br /&gt;      /// equality.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg2"&amp;gt;The first argument to be compared for &lt;br /&gt;      /// equality.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void AreEqual&amp;lt;T&amp;gt;(T arg1, T arg2) {&lt;br /&gt;         if (arg1 == null &amp;amp;&amp;amp; arg2 == null)&lt;br /&gt;            return;&lt;br /&gt;         if (arg1 == null)&lt;br /&gt;            Debug.Assert(false);&lt;br /&gt;         Debug.Assert(arg1.Equals(arg2));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts two specified argiments to be equal to each other.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg1"&amp;gt;The first argument to be compared for &lt;br /&gt;      /// equality.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg2"&amp;gt;The first argument to be compared for &lt;br /&gt;      /// equality.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void AreEqual&amp;lt;T&amp;gt;(T arg1, T arg2, string message, &lt;br /&gt;                                     params object[] args) {&lt;br /&gt;         if (arg1 == null &amp;amp;&amp;amp; arg2 == null)&lt;br /&gt;            return;&lt;br /&gt;         if (arg1 == null)&lt;br /&gt;            Debug.Assert(false, GetMessage(message, args));&lt;br /&gt;         Debug.Assert(arg1.Equals(arg2), GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts two specified argiments to be not equal to each other.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg1"&amp;gt;The first argument to be compared for not &lt;br /&gt;      /// being equal.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg2"&amp;gt;The first argument to be compared for not &lt;br /&gt;      /// being equal.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void AreNotEqual(object arg1, object arg2) {&lt;br /&gt;         if (arg1 == null &amp;amp;&amp;amp; arg2 == null)&lt;br /&gt;            Debug.Assert(false);&lt;br /&gt;         if (arg1 == null)&lt;br /&gt;            return;&lt;br /&gt;         Debug.Assert(!arg1.Equals(arg2));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts two specified argiments to be not equal to each other.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg1"&amp;gt;The first argument to be compared for not &lt;br /&gt;      /// being equal.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg2"&amp;gt;The first argument to be compared for not &lt;br /&gt;      /// being equal.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void AreNotEqual(object arg1, object arg2, string message, &lt;br /&gt;                                     params object[] args) {&lt;br /&gt;         if (arg1 == null &amp;amp;&amp;amp; arg2 == null)&lt;br /&gt;            Debug.Assert(false, GetMessage(message, args));&lt;br /&gt;         if (arg1 == null)&lt;br /&gt;            return;&lt;br /&gt;         Debug.Assert(!arg1.Equals(arg2), GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts two specified argiments to be not equal to each other.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg1"&amp;gt;The first argument to be compared for not &lt;br /&gt;      /// being equal.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg2"&amp;gt;The first argument to be compared for not &lt;br /&gt;      /// being equal.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void AreNotEqual&amp;lt;T&amp;gt;(T arg1, T arg2) {&lt;br /&gt;         if (arg1 == null &amp;amp;&amp;amp; arg2 == null)&lt;br /&gt;            Debug.Assert(false);&lt;br /&gt;         if (arg1 == null)&lt;br /&gt;            return;&lt;br /&gt;         Debug.Assert(!arg1.Equals(arg2));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts two specified argiments to be not equal to each other.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg1"&amp;gt;The first argument to be compared for not &lt;br /&gt;      /// being equal.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="arg2"&amp;gt;The first argument to be compared for not &lt;br /&gt;      /// being equal.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void AreNotEqual&amp;lt;T&amp;gt;(T arg1, T arg2, string message, &lt;br /&gt;                                        params object[] args) {&lt;br /&gt;         if (arg1 == null &amp;amp;&amp;amp; arg2 == null)&lt;br /&gt;            Debug.Assert(false, GetMessage(message, args));&lt;br /&gt;         if (arg1 == null)&lt;br /&gt;            return;&lt;br /&gt;         Debug.Assert(!arg1.Equals(arg2), GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Generates a failing assertion.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void Fail() {&lt;br /&gt;         Debug.Assert(false);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Generates a failing assertion.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void Fail(string message, params object[] args) {&lt;br /&gt;         Debug.Assert(false, GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified value not to be null.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="value"&amp;gt;The value to be asserted not to be null.&lt;br /&gt;      /// &amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsNull(object value) {&lt;br /&gt;         Debug.Assert(value == null);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified value not to be null.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="value"&amp;gt;The value to be asserted not to be null.&lt;br /&gt;      /// &amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      public static void IsNull(object value, string message, &lt;br /&gt;                                params object[] args) {&lt;br /&gt;         Debug.Assert(value == null, GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified value to be null.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="value"&amp;gt;The value to be asserted to be null.&lt;br /&gt;      /// &amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsNotNull(object value) {&lt;br /&gt;         Debug.Assert(value != null);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified value to be null.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="value"&amp;gt;The value to be asserted to be null.&lt;br /&gt;      /// &amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for &lt;br /&gt;      /// specified message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsNotNull(object value, string message, &lt;br /&gt;                                   params object[] args) {&lt;br /&gt;         Debug.Assert(value != null, GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified parameter to be null.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="value"&amp;gt;The parameter to be asserted to be null.&lt;br /&gt;      /// &amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="paramName"&amp;gt;The name of the parameter not to be &lt;br /&gt;      /// null.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;remarks&amp;gt;&lt;br /&gt;      /// The difference between &amp;lt;see cref="NullArg"/&amp;gt; and IsNotNull&lt;br /&gt;      /// is that &amp;lt;see cref="NullArg"/&amp;gt; should be used for parameters &lt;br /&gt;      /// provided to a method. IsNotNull should be used for other use &lt;br /&gt;      /// cases like method return values or conditional variable &lt;br /&gt;      /// initializations.&lt;br /&gt;      /// &amp;lt;/remarks&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void NullArg(object value, string paramName) {&lt;br /&gt;         if (value == null)&lt;br /&gt;            Debug.Fail(string.Concat(paramName + " cannot be null"));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified value to be assignable by a specified &lt;br /&gt;      /// type.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="value"&amp;gt;The value to be asserted.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="expectedType"&amp;gt;The type to validate the specified &lt;br /&gt;      /// value to be assignable from.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsOfType(object value, Type expectedType) {&lt;br /&gt;         if (value == null)&lt;br /&gt;            Debug.Assert(false);&lt;br /&gt;         Debug.Assert(expectedType.IsAssignableFrom(value.GetType()));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified value to be assignable by a specified type.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="value"&amp;gt;The value to be asserted.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="expectedType"&amp;gt;The type to validate the specified &lt;br /&gt;      /// value to be assignable from.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsOfType(object value, Type expectedType, &lt;br /&gt;                                  string message, params object[] args) {&lt;br /&gt;         if (value == null)&lt;br /&gt;            Debug.Assert(false, GetMessage(message, args));&lt;br /&gt;         Debug.Assert(expectedType.IsAssignableFrom(value.GetType()), &lt;br /&gt;                      GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified value not to be assignable by a specified &lt;br /&gt;      /// type.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="value"&amp;gt;The value to be asserted.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="expectedType"&amp;gt;The type to validate the specified &lt;br /&gt;      /// value not to be assignable from.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsNotOfType(object value, Type expectedType) {&lt;br /&gt;         if (value == null)&lt;br /&gt;            Debug.Assert(false);&lt;br /&gt;         Debug.Assert(!expectedType.IsAssignableFrom(value.GetType()));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified value not to be assignable by a specified &lt;br /&gt;      /// type.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="value"&amp;gt;The value to be asserted.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="expectedType"&amp;gt;The type to validate the specified &lt;br /&gt;      /// value not to be assignable from.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsNotOfType(object value, Type expectedType, &lt;br /&gt;                                     string message, params object[] args) {&lt;br /&gt;         if (value == null)&lt;br /&gt;            Debug.Assert(false, GetMessage(message, args));&lt;br /&gt;         Debug.Assert(!expectedType.IsAssignableFrom(value.GetType()), &lt;br /&gt;                      GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a target type to be assignable by a expected type.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="targetType"&amp;gt;The target type to be assignable.&lt;br /&gt;      /// &amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="expectedType"&amp;gt;The expected type to be assignable &lt;br /&gt;      /// by specified target type.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsTypeOf(Type targetType, Type expectedType) {&lt;br /&gt;         Debug.Assert(expectedType.IsAssignableFrom(targetType));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a target type to be assignable by a expected type.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="targetType"&amp;gt;The target type to be assignable.&lt;br /&gt;      /// &amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="expectedType"&amp;gt;The expected type to be assignable &lt;br /&gt;      /// by specified target type.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsTypeOf(Type targetType, Type expectedType, &lt;br /&gt;                                  string message, params object[] args) {&lt;br /&gt;         Debug.Assert(expectedType.IsAssignableFrom(targetType), &lt;br /&gt;                      GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified condition to be true.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="condition"&amp;gt;The condition to be asserted for being &lt;br /&gt;      /// true.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsTrue(bool condition) {&lt;br /&gt;         Debug.Assert(condition);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified condition to be true.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="condition"&amp;gt;The condition to be asserted for being &lt;br /&gt;      /// true.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsTrue(bool condition, string message, &lt;br /&gt;                                params object[] args) {&lt;br /&gt;         Debug.Assert(condition, GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified condition not to be true.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="condition"&amp;gt;The condition to be asserted for not &lt;br /&gt;      /// being true.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsFalse(bool condition) {&lt;br /&gt;         Debug.Assert(!condition);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /// &amp;lt;summary&amp;gt;&lt;br /&gt;      /// Asserts a specified condition not to be true.&lt;br /&gt;      /// &amp;lt;/summary&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="condition"&amp;gt;The condition to be asserted for not &lt;br /&gt;      /// being true.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="message"&amp;gt;The message to be shown when assertion &lt;br /&gt;      /// fails.&amp;lt;/param&amp;gt;&lt;br /&gt;      /// &amp;lt;param name="args"&amp;gt;Optional formatting arguments for specified &lt;br /&gt;      /// message.&amp;lt;/param&amp;gt;&lt;br /&gt;      [Conditional("DEBUG")]&lt;br /&gt;      public static void IsFalse(bool condition, string message, &lt;br /&gt;                                 params object[] args) {&lt;br /&gt;         Debug.Assert(!condition, GetMessage(message, args));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      private static string GetMessage(string message, &lt;br /&gt;                                       params object[] args) {&lt;br /&gt;         if (args != null &amp;amp;&amp;amp; args.Length != 0)&lt;br /&gt;            return string.Format(CultureInfo.InvariantCulture, message, args);&lt;br /&gt;         return message;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-8425026424078791666?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/8425026424078791666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/02/assert-helper-class.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/8425026424078791666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/8425026424078791666'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/02/assert-helper-class.html' title='Assert Helper Class'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-8488178122224623552</id><published>2010-01-23T06:00:00.000-08:00</published><updated>2010-06-05T07:58:45.146-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='.net 4.0'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='threading'/><title type='text'>.NET 4.0 Lazy&lt;T&gt; Class</title><content type='html'>.NET 4.0 and Visual Studio 2010 is raring to go. Current release date is somewhere in May 2010.&lt;br /&gt;&lt;br /&gt;One of the new features of new framework is the &lt;a href="http://msdn.microsoft.com/en-us/library/dd642331(VS.100).aspx"&gt;Lazy&amp;lt;T&amp;gt;&lt;/a&gt; class which supports lazy initialization of objects.&lt;br /&gt;&lt;br /&gt;As I wrote in some of my previous blogs I'm not best friend of (wrong used) &lt;a href="http://en.wikipedia.org/wiki/Lazy_loading"&gt;Lazy Loading&lt;/a&gt;. However, there are some use cases where this is a very powerful feature. Therefore I use the phrase &lt;i&gt;"Lazy Initialization"&lt;/i&gt; instead of &lt;i&gt;"Lazy Loading"&lt;/i&gt; in below samples for Lazy&amp;lt;T&amp;gt; class. &lt;i&gt;"Lazy Loading"&lt;/i&gt; usually implies automatic loading of reference data in a &lt;a href="http://en.wikipedia.org/wiki/Data_access_layer"&gt;Data Access Layer&lt;/a&gt;. When I speak about &lt;i&gt;"Lazy Initialization"&lt;/i&gt; this implies a lazy initialization of some (rare) object properties which require many or unmanaged system resources.&lt;br /&gt;&lt;br /&gt;The following sample class shows a common case where lazy initialization becomes a very useful and often required implementation.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;sealed class Product1 : IProduct {&lt;br /&gt;   // -------------------------------------------------------------------&lt;br /&gt;   public Product1(string name, Stream picture) {&lt;br /&gt;      Name = name;&lt;br /&gt;      Picture = picture;&lt;br /&gt;   }&lt;br /&gt;   // -------------------------------------------------------------------&lt;br /&gt;   public string Name { get; set; }&lt;br /&gt;   public Stream Picture { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The "Picture" property of "Product" class is usually very rare needed in a whole system and it works with (probably) unmanaged resources which might cause a very high memory allocation. Always to initialize the picture of a product which might only be required in a web front-end or a sales application would cause a huge I/O traffic which is not required in system directions like billing or call-center order management.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Lazy&amp;lt;T&amp;gt; Class&lt;/h3&gt;The &lt;i&gt;Lazy&amp;lt;T&amp;gt;&lt;/i&gt; class represents a wrapper class to handle those kind of property initialization.&lt;br /&gt;&lt;br /&gt;As a quote from &lt;a href="http://msdn.microsoft.com/en-us/library/dd997286(VS.100).aspx"&gt;MSDN&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;Although you can write your own code to perform lazy initialization, we recommend that you use Lazy instead. Lazy and its related types also support thread-safety and provide a consistent exception propagation policy.&lt;/i&gt;&lt;/blockquote&gt;If a system already works with its custom implemented lazy initialization, I'd advice to stay with this. If lazy initialization is a new requirement, we shouldn't run into evil &lt;a href="http://en.wikipedia.org/wiki/Not_Invented_Here"&gt;Not Invented Here&lt;/a&gt; software project anti-pattern ;-) and use the existing implementation.&lt;br /&gt;&lt;br /&gt;Here's a list of methods and constructors provided by &lt;i&gt;Lazy&amp;lt;T&amp;gt;&lt;/i&gt; class (descriptions from &lt;a href="http://msdn.microsoft.com/en-us/library/dd642326(VS.100).aspx"&gt;MSDN&lt;/a&gt;):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;ctor(valueFactory Func&amp;lt;T&amp;gt;)&lt;/b&gt;: Initializes a new instance of the Lazy(T) class. When lazy initialization occurs, the specified initialization function is used.&lt;/li&gt;&lt;li&gt;&lt;b&gt;ctor(valueFactory Func&amp;lt;T&amp;gt;, isThreadSafe bool)&lt;/b&gt;: Initializes a new instance of the Lazy(T) class. When lazy initialization occurs, the specified initialization function and initialization mode are used.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Value&lt;/b&gt;: Gets a value that indicates whether lazy initialization has occurred for this Lazy(T) instance.&lt;/li&gt;&lt;li&gt;&lt;b&gt;IsValueCreated&lt;/b&gt;: Gets the lazily initialized value of the current Lazy(T) instance.&lt;/li&gt;&lt;/ul&gt;&lt;i&gt;Lazy&amp;lt;T&amp;gt;&lt;/i&gt; class provides some more methods and constructors, but the above seem to be the most important in my opinion.&lt;br /&gt;&lt;br /&gt;As a side note for &lt;i&gt;isThreadSafe&lt;/i&gt; parameter, a second quote from MSDN:&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;Some Lazy constructor overloads have a Boolean parameter named isThreadSafe that is used to specify whether the Value() property will be accessed from multiple threads. If you intend to access the property from just one thread, pass in false to obtain a modest performance benefit. If you intend to access the property from multiple threads, pass in true to instruct the Lazy instance to correctly handle race conditions in which one thread throws an exception at initialization time. If you use a constructor that does not have the isThreadSafe parameter, the value defaults to true.&lt;/i&gt;&lt;/blockquote&gt;If an application never works with multiple threads, &lt;i&gt;isThreadSafe&lt;/i&gt; parameter with value &lt;b&gt;false&lt;/b&gt; causes a faster execution due to no thread locking overhead.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How to Use&lt;/h3&gt;First, the "Product" class needs to be modified to support lazy initialization. I moved the stream creation into an external factory class&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;// ======================================================================&lt;br /&gt;sealed class Product2 : IProduct {&lt;br /&gt;   // -------------------------------------------------------------------&lt;br /&gt;   public Product2(string name, string fileName) {&lt;br /&gt;      Name = name;&lt;br /&gt;      _picture = new Lazy&amp;lt;Stream&amp;gt;(() =&amp;gt; PictureFactory.GetPicture(fileName), true);&lt;br /&gt;   }&lt;br /&gt;   // -------------------------------------------------------------------&lt;br /&gt;   public string Name { get; set; }&lt;br /&gt;   public Stream Picture {&lt;br /&gt;      get { return _picture.Value; }&lt;br /&gt;      set { _picture = new Lazy&amp;lt;Stream&amp;gt;(() =&amp;gt; value, true); }&lt;br /&gt;   }&lt;br /&gt;   Lazy&amp;lt;Stream&amp;gt; _picture;&lt;br /&gt;}&lt;br /&gt;// ======================================================================&lt;br /&gt;static class PictureFactory {&lt;br /&gt;   // -------------------------------------------------------------------&lt;br /&gt;   // get picture from disc&lt;br /&gt;   public static Stream GetPicture(string fileName) {&lt;br /&gt;      Console.WriteLine("## Lazy Initializing Image ##");&lt;br /&gt;      if (string.IsNullOrEmpty(fileName))&lt;br /&gt;         fileName = @"C:\Temp\not_available.jpg";&lt;br /&gt;      return new FileStream(fileName, FileMode.Open, FileAccess.Read);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Instead of a direct member field mapping of "Picture" property, "Product" class now works with a &lt;i&gt;Lazy&amp;lt;T&amp;gt;&lt;/i&gt; wrapper which only initializes resources when it is requested. This implementation uses the &lt;i&gt;isThreadSafe&lt;/i&gt; parameter with value &lt;b&gt;true&lt;/b&gt; since we will reuse it below in a multi-threaded sample.&lt;br /&gt;&lt;br /&gt;The "fileName" parameter in constructor and factory class to initialize the picture stream is just an example. If no file name was provided, the factory returns the stream of a "not_available.jpg" as default picture (see &lt;a href="http://martinfowler.com/eaaCatalog/specialCase.html"&gt;Special Case&lt;/a&gt; pattern).&lt;br /&gt;&lt;br /&gt;Notice the &lt;i&gt;Console.WriteLine&lt;/i&gt; within the factory class. This will show when data become initialized.&lt;br /&gt;&lt;br /&gt;The following sample creates some products and simulates a rendering of product pictures into console.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;// ======================================================================&lt;br /&gt;class Program {&lt;br /&gt;   // -------------------------------------------------------------------&lt;br /&gt;   static void Main(string[] args) {&lt;br /&gt;      Console.WriteLine("Creating products");&lt;br /&gt;      List&amp;lt;IProduct&amp;gt; products = new List&amp;lt;IProduct&amp;gt;{&lt;br /&gt;         new Product2("Lord of the Rings", null),&lt;br /&gt;         new Product2("Avatar", @"C:\Temp\avatar.jpg"),&lt;br /&gt;      };&lt;br /&gt;&lt;br /&gt;      Console.WriteLine("Loop through products and print picture");&lt;br /&gt;      products.ForEach(p =&amp;gt; ConsolePictureRenderer.PrintPicture(p));&lt;br /&gt;      products.ForEach(p =&amp;gt; ConsolePictureRenderer.PrintPicture(p));&lt;br /&gt;      Console.ReadKey();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;// ======================================================================&lt;br /&gt;static class ConsolePictureRenderer {&lt;br /&gt;   // -------------------------------------------------------------------&lt;br /&gt;   public static void PrintPicture(IProduct product) {&lt;br /&gt;      Console.WriteLine();&lt;br /&gt;      // simulate picture rendering by a simple console output&lt;br /&gt;      Console.WriteLine("Picture of {0}", product.Name);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As shown in console output, picture data become initialized when it becomes accessed. In addition, picture factory is called only once for each instance of a product.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_hBTxNhEL4oY/S1r8Ej2GXjI/AAAAAAAAAFQ/r3Lyu9xD-KU/s1600-h/lazy_init_single.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="180" src="http://1.bp.blogspot.com/_hBTxNhEL4oY/S1r8Ej2GXjI/AAAAAAAAAFQ/r3Lyu9xD-KU/s400/lazy_init_single.png" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;Multi Threaded&lt;/h3&gt;As written above, &lt;i&gt;Lazy&amp;lt;T&amp;gt;&lt;/i&gt; class represents a thread-safe implementation of a lazy initialization class. That means, picture factory class does not need to implement a custom thread locking. It's automatically handled in &lt;i&gt;Lazy&amp;lt;T&amp;gt;&lt;/i&gt; class.&lt;br /&gt;&lt;br /&gt;As a last snippet, we reuse our "Product", "ProductFactory" and "ConsolePictureRenderer" classes from previous sample and change "Main" method to access the product pictures in a multi-threaded environment.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;// ======================================================================&lt;br /&gt;class Program {&lt;br /&gt;   // -------------------------------------------------------------------&lt;br /&gt;   static void Main(string[] args) {&lt;br /&gt;      Console.WriteLine("Creating products");&lt;br /&gt;      List&amp;lt;IProduct&amp;gt; products = new List&amp;lt;IProduct&amp;gt;{&lt;br /&gt;         new Product2("Lord of the Rings", null),&lt;br /&gt;         new Product2("Avatar", @"C:\Temp\test.jpg"),&lt;br /&gt;      };&lt;br /&gt;&lt;br /&gt;      Console.WriteLine("Loop through products and print picture");&lt;br /&gt;      for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;         ThreadPool.QueueUserWorkItem(foo =&amp;gt;&lt;br /&gt;            products.ForEach(p =&amp;gt;&lt;br /&gt;               ConsolePictureRenderer.PrintPicture(p)));&lt;br /&gt;      }&lt;br /&gt;      Console.ReadKey();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, products and their pictures become accessed by four parallel threads. A second look into console output shows, all pictures are still loaded only once, since "Product" class initializes &lt;i&gt;Lazy&amp;lt;T&amp;gt;&lt;/i&gt; class with &lt;i&gt;isThreadSafe&lt;/i&gt; parameter with values &lt;b&gt;true&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_hBTxNhEL4oY/S1r8fuNU9TI/AAAAAAAAAFY/Dk7hBdOjVnI/s1600-h/lazy_init_multi.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="275" src="http://3.bp.blogspot.com/_hBTxNhEL4oY/S1r8fuNU9TI/AAAAAAAAAFY/Dk7hBdOjVnI/s400/lazy_init_multi.png" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;.NET 4.0 &lt;i&gt;Lazy&amp;lt;T&amp;gt;&lt;/i&gt; class is a nice helper when working with large and/or unmanaged resources. Especially its thread-safe implementation increases the usability in a todays multi-processor environment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-8488178122224623552?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/8488178122224623552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/01/net-40-lazy-class.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/8488178122224623552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/8488178122224623552'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/01/net-40-lazy-class.html' title='.NET 4.0 Lazy&amp;lt;T&amp;gt; Class'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_hBTxNhEL4oY/S1r8Ej2GXjI/AAAAAAAAAFQ/r3Lyu9xD-KU/s72-c/lazy_init_single.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-1564230018596915748</id><published>2010-01-18T14:20:00.001-08:00</published><updated>2010-01-18T14:38:05.902-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL CLR'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Concatenation of Text and Binary Data in T-SQL</title><content type='html'>Some month ago, I blogged about "&lt;a href="http://florianreischl.blogspot.com/2009/09/high-performance-string-split-functions.html"&gt;String Split Functions&lt;/a&gt;" in SQL Server, today I'll write about the inverse part of this topic; The concatenation of text and binary data of several rows, using T-SQL (and the available extensions). As we'll see, just like string splitting, there are several ways to skin the cat.&lt;br /&gt;&lt;br /&gt;Topics covered in this blog entry:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Classical, recursive @variable assignment within an SELECT statement&lt;/li&gt;&lt;li&gt;FOR XML&lt;/li&gt;&lt;li&gt;A WHILE loop and utilizing the BLOB data types WRITE() method&lt;/li&gt;&lt;li&gt;SQLCLR&lt;/li&gt;&lt;/ul&gt;Topics not covered in this blog entry:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Recursive @variable assignment within a CURSOR/WHILE-loop. This produces the same memory management as the SELECT based version but in a non-set-based manner.&lt;/li&gt;&lt;li&gt;SQLCLR as a aggregate function. Reason will be described later.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Test Data&lt;/span&gt;&lt;br /&gt;Since we'll speak about performance in below topics, here are two simple tables containing two different kinds of data to be concatenated.&lt;br /&gt;&lt;br /&gt;The below table contains 200 rows with 180,000 characters and bytes per row. This means 36,000,000 characters/bytes will be concatenated.&lt;br /&gt;&lt;pre class="brush: sql;"&gt;CREATE TABLE LargeData (&lt;br /&gt;   Id INT NOT NULL IDENTITY(1,1)&lt;br /&gt;      PRIMARY KEY CLUSTERED&lt;br /&gt;   ,Txt VARCHAR(MAX)&lt;br /&gt;   ,Bin VARBINARY(MAX)&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;-- fill the table with 200 rows 180,000 characters per row&lt;br /&gt;WITH Numbers AS (&lt;br /&gt;   SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) Num&lt;br /&gt;   FROM master.sys.all_columns&lt;br /&gt;)&lt;br /&gt;INSERT INTO LargeData&lt;br /&gt;   SELECT TOP(200)&lt;br /&gt;      -- text data&lt;br /&gt;      REPLICATE(CONVERT(VARCHAR(MAX), NEWID()), 5000)&lt;br /&gt;      -- binary data&lt;br /&gt;      ,CONVERT(VARBINARY(MAX), REPLICATE(CONVERT(VARCHAR(MAX), NEWID()), 5000))&lt;br /&gt;   FROM Numbers;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As a second kind of source data we'll work with a table containing 50,000 rows but only 16 characters and bytes per row. This means 800,000 characters/bytes to be concatenated.&lt;br /&gt;&lt;pre class="brush: sql;"&gt;CREATE TABLE ManyData (&lt;br /&gt;   Id INT NOT NULL IDENTITY(1,1)&lt;br /&gt;      PRIMARY KEY CLUSTERED&lt;br /&gt;   ,Txt VARCHAR(16)&lt;br /&gt;   ,Bin BINARY(16)&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;-- fill the table with 200 rows 180,000 characters per row&lt;br /&gt;WITH Numbers AS (&lt;br /&gt;   SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) Num&lt;br /&gt;   FROM master.sys.all_columns c1, master.sys.all_columns c2&lt;br /&gt;)&lt;br /&gt;INSERT INTO ManyData&lt;br /&gt;   SELECT TOP(50000)&lt;br /&gt;      -- text data&lt;br /&gt;      LEFT(CONVERT(VARCHAR(36), NEWID()), 16)&lt;br /&gt;      -- binary data&lt;br /&gt;      ,CONVERT(VARBINARY(MAX), NEWID())&lt;br /&gt;   FROM Numbers;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For sake of brevity, I'll provide only one sample statement in the following topics. You can find the complete SQL script as attachment at the end of this blog entry.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Classical @variable Assignment&lt;/span&gt;&lt;br /&gt;The classical approach to concatenate data from rows into one column (or variable in our case) is an SELECT statement with a recursive variable assignment.&lt;br /&gt;&lt;pre class="brush: sql;"&gt;DECLARE &lt;br /&gt;   @txt VARCHAR(MAX) = ''&lt;br /&gt;   ,@bin VARBINARY(MAX) = 0x;&lt;br /&gt;&lt;br /&gt;SELECT &lt;br /&gt;      @txt += TextColumn&lt;br /&gt;      ,@bin += BinaryColumn&lt;br /&gt;   FROM AnyTable;&lt;br /&gt;&lt;/pre&gt;(The “+=”-Operator is a new feature of SQL Server 2008. If you work on SQL Server 2005, just replace it with a variable reassignment like “@txt = @txt + TextColumn”. The “+=”-Operator does exactly the same; it’s just a simplified way to write T-SQL.)&lt;br /&gt;&lt;br /&gt;This is generally a good solution due to three facts. It’s easy to use. It’s a set-based solution. It’s fast for less data to be concatenated. On the other hand this kind of concatenation runs into problems if you have to handle many or large data, because all data are copied several times.&lt;br /&gt;&lt;br /&gt;A look into Profiler shows a huge resource usage, especially for concatenating of many rows to be handled. A concatenation of only 800,000 bytes or characters caused over 180,000,000 read and 1,400,000 write operations.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_hBTxNhEL4oY/S1TCygyGomI/AAAAAAAAAEg/ihqn8vOpObE/s1600-h/concat_classic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_hBTxNhEL4oY/S1TCygyGomI/AAAAAAAAAEg/ihqn8vOpObE/s640/concat_classic.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;FOR XML&lt;/span&gt;&lt;br /&gt;This is a kind of tricking another build-in feature of SQL Server 2005 (and further versions). FOR XML is generally made to create XML output from a SELECT statement. However, it can also be used to concatenate data without any XML-style.&lt;br /&gt;&lt;br /&gt;I learned this trick on &lt;a href="http://www.sqlservercentral.com/"&gt;SQLServerCentral.com&lt;/a&gt;. One article that shows the usage is Jeff Moden's article about &lt;a href="http://www.sqlservercentral.com/articles/Test+Data/61572/"&gt;Performance Tuning: Concatenation Functions and Some Tuning Myths&lt;/a&gt;. (Special thanks to &lt;a href="http://www.bluedog67.com/blog/"&gt;Bluedog67&lt;/a&gt; for this link :-) .)&lt;br /&gt;&lt;br /&gt;Another good resource in web for T-SQL is &lt;a href="http://weblogs.sqlteam.com/mladenp/Default.aspx"&gt;Mladen Prajdić's&lt;/a&gt; page where this trick is shown in "&lt;a href="http://weblogs.sqlteam.com/mladenp/archive/2007/06/01/60220.aspx"&gt;SQL Server 2005: Concat values XML Style&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: sql;"&gt;DECLARE @txt VARCHAR(MAX);&lt;br /&gt;SELECT @txt = (SELECT Txt FROM LargeData FOR XML PATH(''));&lt;br /&gt;&lt;/pre&gt;Literally the text to be provided within the PATH(‘’) is made to provide the name of a parent XML element used for the output data. If you provide an empty string you get a concatenated text of all data returned by the query.&lt;br /&gt;&lt;br /&gt;This is a very powerful solution to concatenate text data. Unfortunately it has to be used carefully if source data are unknown. Since this method works with XML, any kind of functional XML characters like “&amp;gt;” or “&amp;amp;” become masked by this method. Binary data cannot be concatenated by XML PATH().&lt;br /&gt;&lt;br /&gt;A look into profiler shows a great resource usage and duration.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_hBTxNhEL4oY/S1TF0no2OEI/AAAAAAAAAEo/fu3syLpb0gg/s1600-h/concat_xml.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_hBTxNhEL4oY/S1TF0no2OEI/AAAAAAAAAEo/fu3syLpb0gg/s640/concat_xml.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;WRITE Method&lt;/span&gt;&lt;br /&gt;SQL Server 2005 introduced the new BLOB data types VARCHAR(MAX), NVARCHAR(MAX) and VARBINARY(MAX). As well as previous BLOB data types (TEXT, NTEXT and IMAGE), also the old BLOB functions like TEXTPTR or UPDATETEXT became marked as deprecated. As a replacement for those functions, SQL Server 2005 introduced a new method called WRITE() which is a data type method - not a usual T-SQL function. This means, it is not called to get a BLOB as a parameter but it is called on a BLOB data type, like methods in a object-oriented programming language.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: sql;"&gt;DECLARE &lt;br /&gt;   @all VARCHAR(MAX) = ''&lt;br /&gt;   ,@buffer VARCHAR(MAX)&lt;br /&gt;   ,@position INT = 0&lt;br /&gt;   ,@len INT&lt;br /&gt;   ,@i INT = 0&lt;br /&gt;   ,@max INT = (SELECT MAX(Id) FROM LargeData);&lt;br /&gt;&lt;br /&gt;WHILE (@i &amp;lt; @max)&lt;br /&gt;BEGIN&lt;br /&gt;   -- get the next row value&lt;br /&gt;   SELECT TOP(1)&lt;br /&gt;         @i = Id&lt;br /&gt;         ,@buffer = Txt&lt;br /&gt;         ,@len = LEN(Txt)&lt;br /&gt;      FROM LargeData&lt;br /&gt;      WHERE Id &amp;gt; @i&lt;br /&gt;      ORDER BY Id;&lt;br /&gt;&lt;br /&gt;   -- add the text to the existing text&lt;br /&gt;   SET @all.WRITE(@buffer, @position, @len);&lt;br /&gt;   SET @position += @len;&lt;br /&gt;END;&lt;br /&gt;&lt;/pre&gt;Unfortunately, there seem to be no way (I know?) to use the WRITE method in a set-based way. It is possible to use it within an UPDATE statement but it is called only once and not for each row of the source data.&lt;br /&gt;&lt;br /&gt;A look into Profiler shows, the WRITE method much faster than the classical approach of variable reassignment. It's two times faster with ten times less resource usage for larger data and it's 60% faster with about four times less resource usage with many data to be concatenated.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_hBTxNhEL4oY/S1TMwtJq_6I/AAAAAAAAAEw/SgXimlzrf-I/s1600-h/concat_write1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_hBTxNhEL4oY/S1TMwtJq_6I/AAAAAAAAAEw/SgXimlzrf-I/s640/concat_write1.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;However, is there a way to get this WRITE method faster than this? As I already wrote above, it can also be used in an UPDATE statement, so this should also be tried with a temp table.&lt;br /&gt;&lt;pre class="brush: sql;"&gt;-- Large Binary&lt;br /&gt;DECLARE &lt;br /&gt;   @all VARBINARY(MAX) = 0x&lt;br /&gt;   ,@i INT = 0&lt;br /&gt;   ,@max INT = (SELECT MAX(Id) FROM LargeData);&lt;br /&gt;&lt;br /&gt;DECLARE @buffer TABLE (Bin VARBINARY(MAX));&lt;br /&gt;&lt;br /&gt;INSERT INTO @buffer&lt;br /&gt;   SELECT 0x;&lt;br /&gt;&lt;br /&gt;WHILE (@i &amp;lt; @max)&lt;br /&gt;BEGIN&lt;br /&gt;   -- get the next row value&lt;br /&gt;   WITH cte AS (&lt;br /&gt;      SELECT TOP(1)&lt;br /&gt;         Id&lt;br /&gt;         ,Bin&lt;br /&gt;      FROM LargeData&lt;br /&gt;      WHERE Id &amp;gt; @i&lt;br /&gt;      ORDER BY Id&lt;br /&gt;   )&lt;br /&gt;   UPDATE b SET&lt;br /&gt;         -- get the next id&lt;br /&gt;         @i = cte.Id&lt;br /&gt;         -- write into temp table&lt;br /&gt;         ,Bin.WRITE(cte.Bin, DATALENGTH(b.Bin), DATALENGTH(cte.Bin))&lt;br /&gt;      FROM @buffer b CROSS JOIN cte&lt;br /&gt;END;&lt;br /&gt;SELECT @all = Bin FROM @buffer;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Sure, the SQL statement is a bit more complicated since we have to use a common table expression to get the (ORDERED) next row of source data, but what's about performance?&lt;br /&gt;&lt;br /&gt;A look into Profiler shows, execution for many, small data didn't really change. On the other hand concatenation of large data became about 80% faster with only 30% resource usage. So this - more complicated - way to use the WRITE method might be a good investment if large data manipulation is needed.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_hBTxNhEL4oY/S1TR-7z_rnI/AAAAAAAAAE4/wzs7BKJ6-7s/s1600-h/concat_write2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_hBTxNhEL4oY/S1TR-7z_rnI/AAAAAAAAAE4/wzs7BKJ6-7s/s640/concat_write2.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;SQLCLR&lt;/span&gt;&lt;br /&gt;Well, if you don't consider to ever enable CLR in SQL Server this blog ends here :-).&lt;br /&gt;&lt;br /&gt;Generally, SQLCLR provides two different ways to perform this concatenation.&lt;br /&gt;&lt;br /&gt;The first way would be a user-defined &lt;i&gt;aggregate&lt;/i&gt; function which gets the text or binary data to be concatenated. This solution would provide a very handy way to be used like this.&lt;br /&gt;&lt;pre class="brush: sql;"&gt;SELECT CONCATENATE_TEXT(Txt) FROM ManyData;&lt;br /&gt;&lt;/pre&gt;Unfortunately, this solution would require to set the resulting assembly to &lt;i&gt;unsafe&lt;/i&gt; mode and server to be configured at &lt;i&gt;TRUSTWORTHY&lt;/i&gt; level. Why? All SQLCLR functions (procedures, functions, ...) are &lt;i&gt;static&lt;/i&gt; methods on a wrapper .NET class and aggregate functions are called again and again for each row to be proceeded. Within this function CLR only get the current value to be handled, what means CLR would have to remember the previous data anywhere in a static (shared) variable. Due to concurrency calls this would have to handled a custom thread-locking to store and get information. I find SQLCLR provides some powerful extensions but an &lt;i&gt;unsafe&lt;/i&gt; assembly tastes bad. Due to this fact, I'll not provide this solution for now. (If anybody is interested in this, please leave a short note and I'll provide this in another blog entry.)&lt;br /&gt;&lt;br /&gt;The second way to handle the concatenation is a simple user-defined &lt;i&gt;scalar&lt;/i&gt; function which gets the SQL query to be executed. This requires a dynamic SQL approach to use the function, though, it is build-in thread safe because it doesn't require any class member variables.&lt;br /&gt;&lt;br /&gt;Here's a C# method to concatenate text data.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;[Microsoft.SqlServer.Server.SqlFunction(&lt;br /&gt;   DataAccess=DataAccessKind.Read,&lt;br /&gt;   IsDeterministic=false,&lt;br /&gt;   IsPrecise=true,&lt;br /&gt;   SystemDataAccess=SystemDataAccessKind.None&lt;br /&gt;   )]&lt;br /&gt;public static SqlChars ConcatText (&lt;br /&gt;   // the sql statement to be executed&lt;br /&gt;   [SqlFacet(IsFixedLength=false ,IsNullable=false ,MaxSize=-1)]&lt;br /&gt;   SqlString sqlIn&lt;br /&gt;   ) {&lt;br /&gt;&lt;br /&gt;   // create a System.Text.StringBuilder to push all text data into.&lt;br /&gt;   StringBuilder buffer = new StringBuilder();&lt;br /&gt;&lt;br /&gt;   // connect to database and execute the provided SQL statement&lt;br /&gt;   using (SqlConnection cn = new SqlConnection("Context Connection=true")) {&lt;br /&gt;      cn.Open();&lt;br /&gt;      using (SqlCommand cmd = new SqlCommand(sqlIn.Value, cn))&lt;br /&gt;      using (SqlDataReader reader = cmd.ExecuteReader()) {&lt;br /&gt;         while (reader.Read()) {&lt;br /&gt;            // get the next string value from reader and append it to buffer&lt;br /&gt;            string str = (string)reader[0];&lt;br /&gt;            buffer.Append(str);&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // return the concatenated string&lt;br /&gt;   return new SqlChars(buffer.ToString());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here's a C# method to concatenate binary data.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;[Microsoft.SqlServer.Server.SqlFunction(&lt;br /&gt;      DataAccess=DataAccessKind.Read,&lt;br /&gt;      IsDeterministic=true,&lt;br /&gt;      IsPrecise=true,&lt;br /&gt;      SystemDataAccess=SystemDataAccessKind.None&lt;br /&gt;      )]&lt;br /&gt;   public static SqlBytes ConcatBinary(&lt;br /&gt;      // the sql statement to be executed&lt;br /&gt;      [SqlFacet(IsFixedLength = false, IsNullable = false, MaxSize = -1)]&lt;br /&gt;      SqlString sqlIn&lt;br /&gt;      ) {&lt;br /&gt;&lt;br /&gt;      // create a System.IO.MemoryStream to push all text data into&lt;br /&gt;      MemoryStream stream = new MemoryStream();&lt;br /&gt;&lt;br /&gt;      // connect to database and execute the provided SQL statement&lt;br /&gt;      using (SqlConnection cn = new SqlConnection("Context Connection=true")) {&lt;br /&gt;         cn.Open();&lt;br /&gt;         using (SqlCommand cmd = new SqlCommand(sqlIn.Value, cn))&lt;br /&gt;         using (SqlDataReader reader = cmd.ExecuteReader()) {&lt;br /&gt;            while (reader.Read()) {&lt;br /&gt;               // get the next binary value from reader and append it to buffer&lt;br /&gt;               byte[] data = (byte[])reader[0];&lt;br /&gt;               stream.Write(data, 0, data.Length);&lt;br /&gt;            }&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;      // important! reset the stream position to the beginning&lt;br /&gt;      stream.Seek(0, SeekOrigin.Begin);&lt;br /&gt;&lt;br /&gt;      return new SqlBytes(stream);&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The call from T-SQL is equal to any other scalar function call.&lt;br /&gt;&lt;pre class="brush: sql;"&gt;DECLARE @bin VARBINARY(MAX);&lt;br /&gt;SELECT @bin = dbo.ConcatBinary('SELECT Bin FROM LargeData');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Due to the fact that SQLCLR (.NET in general) does not know ANSI text like VARCHAR all non-Unicode data have to be translated into Unicode and back into ANSI. Therefore I extended this tests with two additional executions into NVARCHAR variables instead of VARCHAR.&lt;br /&gt;&lt;br /&gt;A look into Profiler shows, only XML transformation is slightly faster than SQLCLR, without any restrictions for functional characters and it fully supports binary concatenation. In case of large text data concatenation into a NVARCHAR variable SQLCLR is even slightly faster than XML.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_hBTxNhEL4oY/S1Ta_iyJChI/AAAAAAAAAFA/oySi_46TY2Q/s1600-h/concat_clr.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_hBTxNhEL4oY/S1Ta_iyJChI/AAAAAAAAAFA/oySi_46TY2Q/s640/concat_clr.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;Classical concatenation by recursive variable assignment is a nice way to handle less, small data. In case of larger or many data it appears to be not the best solution.&lt;br /&gt;&lt;br /&gt;New WRITE method is a nice extension for SQL Server, especially when working with larger data.&lt;br /&gt;&lt;br /&gt;FOR XML PATH('') is a very powerful trick for text data concatenation. Use it (really!), as long as you keep in mind, it is a kind of a hack and should be used carefully.&lt;br /&gt;&lt;br /&gt;We all (including me!) know, there are very less useful ways to use SQLCLR. But concatenation of data as well as &lt;a href="http://florianreischl.blogspot.com/2009/09/high-performance-string-split-functions.html"&gt;string splitting&lt;/a&gt; are some of those and might be considered if this is a common task in a SQL Server 2005/2008 environment.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Attachments&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://sites.google.com/site/florianreischl/blogspot-files/ConcatenateTextAndBinary.sql?attredirects=0&amp;d=1"&gt;SQL Script containing all test tables and statements&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sites.google.com/site/florianreischl/blogspot-files/ConcatBinary.cs?attredirects=0&amp;d=1"&gt;SQLCLR function to concatenate binary data&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sites.google.com/site/florianreischl/blogspot-files/ConcatTexty.cs?attredirects=0&amp;d=1"&gt;SQLCLR function to concatenate text data&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Post Scriptum&lt;/span&gt;&lt;br /&gt;Thanks again to &lt;a href="http://www.bluedog67.com/blog/"&gt;Bluedog67&lt;/a&gt;, who showed me another blog about string concatenation by &lt;a href="http://www.simple-talk.com/author/anith-sen/"&gt;Anith Sen&lt;/a&gt; at:&lt;br /&gt;&lt;a href="http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/"&gt;Concatenating Row Values in Transact-SQL&lt;/a&gt;&lt;br /&gt;It also covers the CLR aggregate function.&lt;br /&gt;&lt;br /&gt;... didn't know this blog entry before...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-1564230018596915748?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/1564230018596915748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/01/concatenation-of-text-and-binary-data.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/1564230018596915748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/1564230018596915748'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/01/concatenation-of-text-and-binary-data.html' title='Concatenation of Text and Binary Data in T-SQL'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_hBTxNhEL4oY/S1TCygyGomI/AAAAAAAAAEg/ihqn8vOpObE/s72-c/concat_classic.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-7154888742706098756</id><published>2010-01-14T10:07:00.000-08:00</published><updated>2010-01-14T11:58:19.431-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>Bug in SQL Profiler when working Table-Valued Parameters and DATETIME</title><content type='html'>Just provided a new bug note at &lt;a href="https://connect.microsoft.com/SQLServer/"&gt;Microsoft® SQL Server Connect&lt;/a&gt;:&lt;br /&gt;&lt;a href="https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=524961"&gt;Profiler shows DATETIME for TVP as DATETIME2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you work with table-valued types and table-valued parameters provided by a front-end application you get an invalid &lt;a href="http://msdn.microsoft.com/en-us/library/aa173918(SQL.80).aspx"&gt;SQL Profiler&lt;/a&gt; output for &lt;i&gt;DATETIME&lt;/i&gt; columns. Profiler shows &lt;i&gt;DATETIME&lt;/i&gt; column inserts as &lt;i&gt;DATETIME&lt;b&gt;&lt;u&gt;2&lt;/u&gt;&lt;/b&gt;&lt;/i&gt; values (like '2010-01-14 18:38:09.2100000'). The problem with this output are the nano-second digits which cannot be converted to &lt;i&gt;DATETIME&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;For anybody who is interested, here a short description how to reproduce.&lt;br /&gt;&lt;br /&gt;Create a new table-valued type in SQL Server.&lt;br /&gt;&lt;pre class="brush: sql;"&gt;CREATE TYPE FooType AS TABLE (&lt;br /&gt;   Dt DATETIME&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And a little C# application that uses this table-valued type by executing an &lt;i&gt;SqlCommand&lt;/i&gt;.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;class TestEnumerator : IEnumerable&lt;sqldatarecord&gt; {&lt;br /&gt;   public IEnumerator&lt;sqldatarecord&gt; GetEnumerator() {&lt;br /&gt;      // create meta data for the table-valued parameter&lt;br /&gt;      SqlMetaData[] meta = new SqlMetaData[] {&lt;br /&gt;         new SqlMetaData("Dt", SqlDbType.DateTime)&lt;br /&gt;      };&lt;br /&gt;&lt;br /&gt;      // create a single record to be returned as enumerator&lt;br /&gt;      SqlDataRecord record = new SqlDataRecord(meta);&lt;br /&gt;      record.SetDateTime(0, DateTime.Now);&lt;br /&gt;      // return the record as enumerator value&lt;br /&gt;      yield return record;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   IEnumerator IEnumerable.GetEnumerator() {&lt;br /&gt;      return this.GetEnumerator();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;class Program {&lt;br /&gt;   static void Main(string[] args) {&lt;br /&gt;      string cnStr = Properties.Settings.Default.SandboxConnectionString;&lt;br /&gt;&lt;br /&gt;      // connect to the database and create a new sql command that simply &lt;br /&gt;      // returns the count of rows within a table-valued parameter&lt;br /&gt;      using (SqlConnection cn = new SqlConnection(cnStr))&lt;br /&gt;      using (SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM @t", cn)) {&lt;br /&gt;         cn.Open();&lt;br /&gt;&lt;br /&gt;         // create and configure the table-valued parameter&lt;br /&gt;         SqlParameter p = new SqlParameter("@t", SqlDbType.Structured);&lt;br /&gt;         // specify the table-valued type&lt;br /&gt;         p.TypeName = "FooType";&lt;br /&gt;         p.Value = new TestEnumerator();&lt;br /&gt;         cmd.Parameters.Add(p);&lt;br /&gt;&lt;br /&gt;         // execute the command&lt;br /&gt;         object result = cmd.ExecuteScalar();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now start SQL Profiler and enable the "RPC:Completed" event. Start the C# application and you will get the following trace output:&lt;br /&gt;&lt;pre class="brush: sql;"&gt;declare @p3 dbo.FooType&lt;br /&gt;insert into @p3 values('2010-01-14 18:38:09.2100000')&lt;br /&gt;&lt;br /&gt;exec sp_executesql N'SELECT COUNT(*) FROM @t',N'@t FooType READONLY',@t=@p3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The error occurs if you try to run this SQL in SSMS for debugging.&lt;br /&gt;&lt;pre "brush: plain;"&gt;Msg 241, Level 16, State 1, Line 7&lt;br /&gt;Conversion failed when converting date and/or time from character string.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-7154888742706098756?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/7154888742706098756/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/01/bug-in-sql-profiler-when-working-table.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7154888742706098756'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7154888742706098756'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/01/bug-in-sql-profiler-when-working-table.html' title='Bug in SQL Profiler when working Table-Valued Parameters and DATETIME'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-4546149139739493451</id><published>2010-01-11T06:55:00.000-08:00</published><updated>2010-01-11T06:55:39.313-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><title type='text'>How to Enable First Chance Exceptions in Visual Studio</title><content type='html'>This blog entry explains how to enable first chance exceptions in Visual Studio. I explained this several people, so this might be a basic configuration but there are many people who apparently do not yet know.&lt;br /&gt;&lt;br /&gt;First chance exceptions means that Visual Studio immediately stops when any kind of exception (e.g. &lt;i&gt;NullReferenceException&lt;/i&gt; or &lt;i&gt;InvalidOperationException&lt;/i&gt;) occurs. Often first chance exceptions are disabled in Visual Studio by default installation. This causes exceptions that can be caught by a catch-block, wherever in call stack, will not stop the debugger at the point of exception creation. The debugger only stops if an exception cannot be handled by any catch-block. So a developer often does not see where the exception was created and thrown.&lt;br /&gt;&lt;br /&gt;Depending on your installation of Visual Studio you first have to add an additional command to the menu of your IDE. Therefore select "Tools" menu and click "Customize...".&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_hBTxNhEL4oY/S0s1Hs_QZzI/AAAAAAAAADQ/HvUKIHhqh8Q/s1600-h/vs_ex_01.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_hBTxNhEL4oY/S0s1Hs_QZzI/AAAAAAAAADQ/HvUKIHhqh8Q/s640/vs_ex_01.PNG" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The "Customize" dialog opens where you can select additional items to be added to your menu or toolbars. Activate the "Commands" tab and select "Debug" in the left list with title "Categories". Select "Exceptions..." item from the right list with title "Commands" and drag it into your "Debug" menu on top of Visual Studio.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_hBTxNhEL4oY/S0s2Jy2Q28I/AAAAAAAAADY/XB0O_fKumJk/s1600-h/vs_ex_02.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_hBTxNhEL4oY/S0s2Jy2Q28I/AAAAAAAAADY/XB0O_fKumJk/s640/vs_ex_02.PNG" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Now you can close the Customize dialog by hitting the "Close" button.&lt;br /&gt;&lt;br /&gt;Go to menu and select the newly added menu item "Exceptions..." in "Debug" top menu. The new "Exceptions" dialog appears where you can configure the exception behavior of Visual Studio debug sessions. Within the shown list select "Common Language Runtime Exceptions" and activate the "Thrown" check-box on the right side.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_hBTxNhEL4oY/S0s3B-D2OoI/AAAAAAAAADg/GVr0AkPgcFI/s1600-h/vs_ex_03.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_hBTxNhEL4oY/S0s3B-D2OoI/AAAAAAAAADg/GVr0AkPgcFI/s640/vs_ex_03.PNG" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;As you noticed, you also can expand each exception category to select any special kind of exception you want to enable or disable for first chance exception handling. This is useful for some special debugging sessions, but most times its best to force Visual Studio to stop at any kind of thrown exception.&lt;br /&gt;&lt;br /&gt;To close the dialog use the "Ok" button.&lt;br /&gt;&lt;br /&gt;Now you can start debugging your project and Visual Studio stops as soon as any kind of exception occurs.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_hBTxNhEL4oY/S0s6KrgRzkI/AAAAAAAAADo/wAlWuKzhGME/s1600-h/vs_ex_04.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_hBTxNhEL4oY/S0s6KrgRzkI/AAAAAAAAADo/wAlWuKzhGME/s640/vs_ex_04.PNG" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Happy coding :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-4546149139739493451?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/4546149139739493451/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/01/how-to-enable-first-chance-exceptions.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/4546149139739493451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/4546149139739493451'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/01/how-to-enable-first-chance-exceptions.html' title='How to Enable First Chance Exceptions in Visual Studio'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_hBTxNhEL4oY/S0s1Hs_QZzI/AAAAAAAAADQ/HvUKIHhqh8Q/s72-c/vs_ex_01.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-6911526410755388836</id><published>2010-01-09T07:58:00.000-08:00</published><updated>2011-08-22T06:20:08.298-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>O/R-Mapper - Enemy Mine</title><content type='html'>Those days, I here many discussions pro and contra O/R-Mappers (ORMs). &lt;a href="http://www.wiseman-wiseguy.blogspot.com/"&gt;Jack Corbett&lt;/a&gt;, a professional SQL guy I really regard speaks at &lt;a href="http://www.sqlsaturday.com/32/schedule.aspx"&gt;SQLSaturday#32&lt;/a&gt; about &lt;a href="http://wiseman-wiseguy.blogspot.com/2009/12/speaking-at-sqlsaturday-32-tampa.html"&gt;"Why Should I Use Stored Procedures?"&lt;/a&gt; in relation to ORM tools. I just had an own, nice discussion with several guys at:&lt;br /&gt;&lt;a href="http://www.mycsharp.de/wbb2/thread.php?threadid=79034"&gt;Sind O/R-Mapper potentiell ein schleichender Tod?&lt;/a&gt; (a German C# developer forum)&lt;br /&gt;Try of a English translation:&lt;br /&gt;Are O/R-Mapper a potential sneaking dead?&lt;br /&gt;&lt;br /&gt;The quint essence of this discussion was. Most, experienced developers generally like &lt;i&gt;the idea&lt;/i&gt; of those ORMs but currently they don't trust them in larger projects.&lt;br /&gt;&lt;br /&gt;In this blog entry I'll try to address my main problems with O/R-Mappers.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Holy Cow for Consumers&lt;/h3&gt;&lt;span class="text"&gt;Often I saw developers who forgot the "R" (relational) within the O&lt;b&gt;R&lt;/b&gt;-Mapper. It's a mapping tool to bring relational data into an domain object model. However, there is still a relational database system behind the curtain. It's very very very important to never forget this.&lt;br /&gt;&lt;br /&gt;What does this mean?&lt;br /&gt;&lt;br /&gt;The first thing is the query support. ORMs usually provide an object oriented way to handle database queries. This is a nice feature (if correct implemented by the ORM), but it's impossible for any tool to cover the whole power of RDBMS specific SQL. Those queries are usually fine for simple queries like "give me a customer by her code" or "give me the not finished orders of a specific customer". That means queries on direct fields on the base table of a domain object and queries over one or maybe two related tables. As soon as you hit this boundary, you should consider to implement a custom SQL query (or procedure). Especially things like "LEFT JOINs", "OR" or the disingenuous "IN" should always be done by custom SQL, since it directly shows potential problems - as execution plans in SQL Server.&lt;br /&gt;&lt;br /&gt;The second, most times wrong used feature of O/R-Mappers is lazy loading. There are some, very rare(!) business cases where lazy loading is a good thing and should be used. Whenever I use lazy loading I have to keep in mind that any access to a not yet loaded relation causes an own SQL query fired to the database server. Using lazy loading in form of always just load the root object and let the mapper load every information when I need it quickly ends up in hundreds or thousands or more single queries stressing the server. Let me quote &lt;a href="http://martinfowler.com"&gt;Martin Fowler&lt;/a&gt; who calls this a &lt;i&gt;"ripple loading"&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;It's important to always keep in mind, an O/R-Mapper is a tool and nothing more, really. It's a tool to automate some boring work like simple 1:1 mapping of relational data into a domain object and automate some basic queries. Depending on the technology which is covered by the tool - relational databases - every ORM is always a weak tool. That doesn't mean that developers of ORMs doing a bad job! The weakness depends on the fact that an ORM always can only cover a very small and simple part of the SQL possibilities of a todays RDBMS. They especially cannot handle a professional query tuning like analyzing execution plans which may point a completely different query for same result on different databases - sometimes even for the same RDBMS.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;h3&gt;The Holy Cow Mislead by the Publishers&lt;/h3&gt;&lt;span class="text"&gt;Sadly, some of the problems addressed above are often caused on the way how those tools are promoted (or implemented). Every common O/R-Mapper is promoted as &lt;i&gt;"the all-in-one"&lt;/i&gt;. However, I think an ORM will never be able to handle every special case - from database and domain model side.&lt;br /&gt;&lt;br /&gt;As I pointed the "R" as the most common potential problem while consuming an ORM; the "M" (mapper) is my main issue of todays OR&lt;b&gt;M&lt;/b&gt;s. Sure, the mapping is the main part of an O/R-Mapper. It maps relational data into a domain object model and vice versa. Unfortunately, all mappers I know encapsulate this part of the tool as a black-box. My problem with this encapsulation is an &lt;b&gt;build-in&lt;/b&gt; tight coupling between database and domain model which is restricted to the mapping strength of the used tool. I think the only restriction of modelling should be the experiences of the developers, DBAs and architects.&lt;br /&gt;&lt;br /&gt;What does this mean?&lt;br /&gt;&lt;br /&gt;In the domain model, this tight coupling sometimes disables a more normalized form of objects than it is available by the database. I don't speak about a denormalized database but often an domain object model uses more than one object for one table. While a "Orders" table might contain customer information like "CustomerOrderRef" or "RequestedDeliveryDate", the "Order" domain object can contain another "CustomerInfo" reference which holds all the customer specific information. As long as those related objects are mutable (what means they provider setter methods or properties), abstracting ORMs like &lt;a href="https://www.hibernate.org/343.html"&gt;NHibernate&lt;/a&gt; or &lt;a href="http://msdn.microsoft.com/en-us/library/aa697427(VS.80).aspx"&gt;Entity Framework&lt;/a&gt; are able to handle the mapping. However, if there is a mapping to a immutable value object they hit the wall. A good sample (again by Martin Fowler) for a mapping of columns to a immutable object is a &lt;i&gt;Money&lt;/i&gt;-object (don't mis with the SQL Server data type MONEY). Money usually has two different information an Amount and a Currency. Usually a table usually contains an "Amount" column and a "CurrencyId" column, but those non normalized information seem to be not the best design in a domain model, especially if I want to be able to calculate with those money information. I'd be glad if I could inject the existing mapping with some custom work without having to provide the database columns in my domain objects.&lt;br /&gt;&lt;br /&gt;On the other hand the database can be more normalized than a domain model, what is more common known situation. Again, ORMs like NHibernate and Entity Framework support simple denormalization of 1:1 table relations into a domain model - with some restrictions. A good sample where ORMs are impossible to handle the mapping are &lt;a href="http://ycmi.med.yale.edu/nadkarni/eav_CR_contents.htm"&gt;EAV/CR&lt;/a&gt; tables. Generally EAV/CR is not a common database design today but there are good reasons to use them for some special cases. If I think about a software of a sports club which holds describing information for each member. Storing all playing skills of all members for any kind of sport. This seems to be almost impossible in a usual relational database design. At this point I'd like to be able to map this very special form of data into my domain object model without leaving the whole universe of the rest of my model by defining my "Member" as &lt;a href="http://en.wikipedia.org/wiki/Plain_Old_CLR_Object"&gt;POCO&lt;/a&gt; (or &lt;a href="http://en.wikipedia.org/wiki/Plain_Old_Java_Object"&gt;POJO&lt;/a&gt; in case of Java) which is not part of my mapper.&lt;br /&gt;&lt;br /&gt;Last but not least, many ORMs access way to may information what causes a huge, not needed I/O overhead. An order object and table might contain several information which are needed for very different parts of a system like customer, shipping and billing information. ORMs either always load and write all the information or work with a property/column based lazy loading - what usually becomes the hardest kind of ripple loading. There are some main information like the table identity and an "OrderNumber" which are usually needed for almost any part of the system but I don't need all the other information whenever I load an order from the database.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;h3&gt;My Wishes for the Future&lt;/h3&gt;&lt;span class="text"&gt;From the consumer side, I hope developers come back to the mindset that an O/R-Mapper is a (weak) tool and nothing more. Whenever they create a new ORM query object, reconsider if the query that will be created fits the possibilities of the mapper.&lt;br /&gt;&lt;br /&gt;From the publisher side, I don't look for a mapper that handles mapping of value objects or EAV/CR tables. These have just have been samples for boundaries of mappers - maybe there is even a mapper which supports one of those features. I'm looking for an O/R-Mapper which knows its limits and allows a tailor made mapping without the must of leaving the whole universe of the mapper for change tracking, transaction handling and other useful features.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;h3&gt;A current Spare Time Project&lt;/h3&gt;&lt;span class="text"&gt;I'm thinking several month about O/R-Mappers, their strengths and their weaknesses. I tried several mappers and after some short euphorias I hit back the ground due to existing restrictions which could not be handled without some ugly workarounds. About 2 month ago, I started to think (and implement) a own version of an ORM. After more than 150 classes and the first tests it seems to fit my requirements but who knows... Maybe it dies while implementation phase. Maybe it works and I'll use it in one of my future projects. Maybe I'll publish it. If I publish it, maybe it becomes yet another dead born O/R-Mapper in the internet, maybe there will be some guys and/or gals who try and hate it, maybe there will be some guys and/or gals who try and enjoy it.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-6911526410755388836?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/6911526410755388836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/01/or-mapper-enemy-mine.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/6911526410755388836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/6911526410755388836'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/01/or-mapper-enemy-mine.html' title='O/R-Mapper - Enemy Mine'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-2570733876826723226</id><published>2010-01-08T14:45:00.000-08:00</published><updated>2010-01-09T03:38:08.592-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Generic C# RingBuffer</title><content type='html'>Today I'll share an almost coding only blog entry.&lt;br /&gt;&lt;br /&gt;A &lt;i&gt;RingBuffer&lt;/i&gt; (aka. &lt;a href="http://en.wikipedia.org/wiki/Circular_buffer"&gt;Circular Buffer&lt;/a&gt;) is a kind of a collection with a fixed maximal count of items to be stored within. After it reaches its capacity, the next insertion of a new items causes the first item to be overwritten.&lt;br /&gt;&lt;br /&gt;These kind of objects is especially useful when working with large amounts of data where it is required to look back at some previous items (e.g. for validation). A RingBuffer provides this functionality by avoiding to hold all the data ever stored within.&lt;br /&gt;&lt;br /&gt;This can be imagined like a window when driving by train. We see the next tree and the previous some, but we don't see all the trees since the journey started.&lt;br /&gt;&lt;br /&gt;Before I wrote this blog entry, I searched the .NET framework and some common web sources. I have to say, I was wondering that I did not find another (working) .NET implementation of a &lt;i&gt;RingBuffer&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Here is my version of a generic &lt;i&gt;RingBuffer&lt;/i&gt;. Source file and unit tests are attached at the bottom of this post.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;/*&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Collections;&lt;br /&gt;using System.Diagnostics;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Represents a fixted length ring buffer to store a specified maximal count of items within.&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;typeparam name="T"&amp;gt;The generic type of the items stored within the ring buffer.&amp;lt;/typeparam&amp;gt;&lt;br /&gt;[DebuggerDisplay("Count = {Count}")]&lt;br /&gt;public class RingBuffer&amp;lt;T&amp;gt; : IList&amp;lt;T&amp;gt;, ICollection&amp;lt;T&amp;gt;, &lt;br /&gt;                             IEnumerable&amp;lt;T&amp;gt;, IEnumerable {&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Creates a new instance of a &amp;lt;see cref="RingBuffer&amp;amp;lt;T&amp;amp;gt;"/&amp;gt; with a &lt;br /&gt;   /// specified cache size.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="capacity"&amp;gt;The maximal count of items to be stored within &lt;br /&gt;   /// the ring buffer.&amp;lt;/param&amp;gt;&lt;br /&gt;   public RingBuffer(int capacity) {&lt;br /&gt;      // validate capacity&lt;br /&gt;      if (capacity &amp;lt;= 0)&lt;br /&gt;         throw new ArgumentException("Must be greater than zero", "capacity");&lt;br /&gt;      // set capacity and init the cache&lt;br /&gt;      Capacity = capacity;&lt;br /&gt;      _buffer = new T[capacity];&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// the internal buffer&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   T[] _buffer;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// The all-over position within the ring buffer. The position &lt;br /&gt;   /// increases continously by adding new items to the buffer. This &lt;br /&gt;   /// value is needed to calculate the current relative position within the &lt;br /&gt;   /// buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   int _position;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// The current version of the buffer, this is required for a correct &lt;br /&gt;   /// exception handling while enumerating over the items of the buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   long _version;&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Gets or sets an item for a specified position within the ring buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="index"&amp;gt;The position to get or set an item.&amp;lt;/param&amp;gt;&lt;br /&gt;   /// &amp;lt;returns&amp;gt;The fond item at the specified position within the ring buffer.&lt;br /&gt;   /// &amp;lt;/returns&amp;gt;&lt;br /&gt;   /// &amp;lt;exception cref="IndexOutOfRangeException"&amp;gt;&amp;lt;/exception&amp;gt;&lt;br /&gt;   public T this[int index] {&lt;br /&gt;      get {&lt;br /&gt;         // validate the index&lt;br /&gt;         if (index &amp;lt; 0 || index &amp;gt;= Count)&lt;br /&gt;            throw new IndexOutOfRangeException();&lt;br /&gt;         // calculate the relative position within the rolling base array&lt;br /&gt;         int index2 = (_position - Count + index) % Capacity;&lt;br /&gt;         return _buffer[index2]; &lt;br /&gt;      }&lt;br /&gt;      set { Insert(index, value); }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Gets the maximal count of items within the ring buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   public int Capacity { get; private set; }&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Get the current count of items within the ring buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   public int Count { get; private set; }&lt;br /&gt;   &lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Adds a new item to the buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="item"&amp;gt;The item to be added to the buffer.&amp;lt;/param&amp;gt;&lt;br /&gt;   public void Add(T item) {&lt;br /&gt;      // add a new item to the current relative position within the&lt;br /&gt;      // buffer and increase the position&lt;br /&gt;      _buffer[_position++ % Capacity] = item;&lt;br /&gt;      // increase the count if capacity is not yet reached&lt;br /&gt;      if (Count &amp;lt; Capacity) Count++;&lt;br /&gt;      // buffer changed; next version&lt;br /&gt;      _version++;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Clears the whole buffer and releases all referenced objects &lt;br /&gt;   /// currently stored within the buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   public void Clear() {&lt;br /&gt;      for (int i = 0; i &amp;lt; Count; i++)&lt;br /&gt;         _buffer[i] = default(T);&lt;br /&gt;      _position = 0;&lt;br /&gt;      Count = 0;&lt;br /&gt;      _version++;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Determines if a specified item is currently present within&lt;br /&gt;   /// the buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="item"&amp;gt;The item to search for within the current&lt;br /&gt;   /// buffer.&amp;lt;/param&amp;gt;&lt;br /&gt;   /// &amp;lt;returns&amp;gt;True if the specified item is currently present within &lt;br /&gt;   /// the buffer; otherwise false.&amp;lt;/returns&amp;gt;&lt;br /&gt;   public bool Contains(T item) {&lt;br /&gt;      int index = IndexOf(item);&lt;br /&gt;      return index != -1;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Copies the current items within the buffer to a specified array.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="array"&amp;gt;The target array to copy the items of &lt;br /&gt;   /// the buffer to.&amp;lt;/param&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="arrayIndex"&amp;gt;The start position witihn the target&lt;br /&gt;   /// array to start copying.&amp;lt;/param&amp;gt;&lt;br /&gt;   public void CopyTo(T[] array, int arrayIndex) {&lt;br /&gt;      for (int i = 0; i &amp;lt; Count; i++) {&lt;br /&gt;         array[i + arrayIndex] = _buffer[(_position - Count + i) % Capacity];&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Gets an enumerator over the current items within the buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;returns&amp;gt;An enumerator over the current items within the buffer.&lt;br /&gt;   /// &amp;lt;/returns&amp;gt;&lt;br /&gt;   public IEnumerator&amp;lt;T&amp;gt; GetEnumerator() {&lt;br /&gt;      long version = _version;&lt;br /&gt;      for (int i = 0; i &amp;lt; Count; i++) {&lt;br /&gt;         if (version != _version)&lt;br /&gt;            throw new InvalidOperationException("Collection changed");&lt;br /&gt;         yield return this[i];&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Gets the position of a specied item within the ring buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="item"&amp;gt;The item to get the current position for.&amp;lt;/param&amp;gt;&lt;br /&gt;   /// &amp;lt;returns&amp;gt;The zero based index of the found item within the &lt;br /&gt;   /// buffer. If the item was not present within the buffer, this&lt;br /&gt;   /// method returns -1.&amp;lt;/returns&amp;gt;&lt;br /&gt;   public int IndexOf(T item) {&lt;br /&gt;      // loop over the current count of items&lt;br /&gt;      for (int i = 0; i &amp;lt; Count; i++) {&lt;br /&gt;         // get the item at the relative position within the internal array&lt;br /&gt;         T item2 = _buffer[(_position - Count + i) % Capacity];&lt;br /&gt;         // if both items are null, return true&lt;br /&gt;         if (null == item &amp;amp;&amp;amp; null == item2)&lt;br /&gt;            return i;&lt;br /&gt;         // if equal return the position&lt;br /&gt;         if (item != null &amp;amp;&amp;amp; item.Equals(item2))&lt;br /&gt;            return i;&lt;br /&gt;      }&lt;br /&gt;      // nothing found&lt;br /&gt;      return -1;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Inserts an item at a specified position into the buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="index"&amp;gt;The position within the buffer to add &lt;br /&gt;   /// the new item.&amp;lt;/param&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="item"&amp;gt;The new item to be added to the buffer.&amp;lt;/param&amp;gt;&lt;br /&gt;   /// &amp;lt;exception cref="IndexOutOfRangeException"&amp;gt;&amp;lt;/exception&amp;gt;&lt;br /&gt;   /// &amp;lt;remarks&amp;gt;&lt;br /&gt;   /// If the specified index is equal to the current count of items&lt;br /&gt;   /// within the buffer, the specified item will be added.&lt;br /&gt;   /// &lt;br /&gt;   /// &amp;lt;b&amp;gt;Warning&amp;lt;/b&amp;gt;&lt;br /&gt;   /// Frequent usage of this method might become a bad idea if you are &lt;br /&gt;   /// working with a large buffer capacity. The insertion of an item&lt;br /&gt;   /// at a specified position within the buffer causes causes all present &lt;br /&gt;   /// items below the specified position to be moved one position.&lt;br /&gt;   /// &amp;lt;/remarks&amp;gt;&lt;br /&gt;   public void Insert(int index, T item) {&lt;br /&gt;      // validate index&lt;br /&gt;      if (index &amp;lt; 0 || index &amp;gt; Count)&lt;br /&gt;         throw new IndexOutOfRangeException();&lt;br /&gt;      // add if index equals to count&lt;br /&gt;      if (index == Count) {&lt;br /&gt;         Add(item);&lt;br /&gt;         return;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      // get the maximal count of items to be moved&lt;br /&gt;      int count = Math.Min(Count, Capacity - 1) - index;&lt;br /&gt;      // get the relative position of the new item within the buffer&lt;br /&gt;      int index2 = (_position - Count + index) % Capacity;&lt;br /&gt;&lt;br /&gt;      // move all items below the specified position&lt;br /&gt;      for (int i = index2 + count; i &amp;gt; index2; i--) {&lt;br /&gt;         int to = i % Capacity;&lt;br /&gt;         int from = (i - 1) % Capacity;&lt;br /&gt;         _buffer[to] = _buffer[from];&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      // set the new item&lt;br /&gt;      _buffer[index2] = item;&lt;br /&gt;&lt;br /&gt;      // adjust storage information&lt;br /&gt;      if (Count &amp;lt; Capacity) {&lt;br /&gt;         Count++;&lt;br /&gt;         _position++;&lt;br /&gt;      }&lt;br /&gt;      // buffer changed; next version&lt;br /&gt;      _version++;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Removes a specified item from the current buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="item"&amp;gt;The item to be removed.&amp;lt;/param&amp;gt;&lt;br /&gt;   /// &amp;lt;returns&amp;gt;True if the specified item was successfully removed&lt;br /&gt;   /// from the buffer; otherwise false.&amp;lt;/returns&amp;gt;&lt;br /&gt;   /// &amp;lt;remarks&amp;gt;&lt;br /&gt;   /// &amp;lt;b&amp;gt;Warning&amp;lt;/b&amp;gt;&lt;br /&gt;   /// Frequent usage of this method might become a bad idea if you are &lt;br /&gt;   /// working with a large buffer capacity. The removing of an item &lt;br /&gt;   /// requires a scan of the buffer to get the position of the specified&lt;br /&gt;   /// item. If the item was found, the deletion requires a move of all &lt;br /&gt;   /// items stored abouve the found position.&lt;br /&gt;   /// &amp;lt;/remarks&amp;gt;&lt;br /&gt;   public bool Remove(T item) {&lt;br /&gt;      // find the position of the specified item&lt;br /&gt;      int index = IndexOf(item);&lt;br /&gt;      // item was not found; return false&lt;br /&gt;      if (index == -1)&lt;br /&gt;         return false;&lt;br /&gt;      // remove the item at the specified position&lt;br /&gt;      RemoveAt(index);&lt;br /&gt;      return true;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Removes an item at a specified position within the buffer.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;param name="index"&amp;gt;The position of the item to be removed.&amp;lt;/param&amp;gt;&lt;br /&gt;   /// &amp;lt;exception cref="IndexOutOfRangeException"&amp;gt;&amp;lt;/exception&amp;gt;&lt;br /&gt;   /// &amp;lt;remarks&amp;gt;&lt;br /&gt;   /// &amp;lt;b&amp;gt;Warning&amp;lt;/b&amp;gt;&lt;br /&gt;   /// Frequent usage of this method might become a bad idea if you are &lt;br /&gt;   /// working with a large buffer capacity. The deletion requires a move &lt;br /&gt;   /// of all items stored abouve the found position.&lt;br /&gt;   /// &amp;lt;/remarks&amp;gt;&lt;br /&gt;   public void RemoveAt(int index) {&lt;br /&gt;      // validate the index&lt;br /&gt;      if (index &amp;lt; 0 || index &amp;gt;= Count)&lt;br /&gt;         throw new IndexOutOfRangeException();&lt;br /&gt;      // move all items above the specified position one step&lt;br /&gt;      // closer to zeri&lt;br /&gt;      for (int i = index; i &amp;lt; Count - 1; i++) {&lt;br /&gt;         // get the next relative target position of the item&lt;br /&gt;         int to = (_position - Count + i) % Capacity;&lt;br /&gt;         // get the next relative source position of the item&lt;br /&gt;         int from = (_position - Count + i + 1) % Capacity;&lt;br /&gt;         // move the item&lt;br /&gt;         _buffer[to] = _buffer[from];&lt;br /&gt;      }&lt;br /&gt;      // get the relative position of the last item, which becomes empty&lt;br /&gt;      // after deletion and set the item as empty&lt;br /&gt;      int last = (_position - 1) % Capacity;&lt;br /&gt;      _buffer[last] = default(T);&lt;br /&gt;      // adjust storage information&lt;br /&gt;      _position--;&lt;br /&gt;      Count--;&lt;br /&gt;      // buffer changed; next version&lt;br /&gt;      _version++;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// Gets if the buffer is read-only. This method always returns false.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   bool ICollection&amp;lt;T&amp;gt;.IsReadOnly { get { return false; } }&lt;br /&gt;&lt;br /&gt;   /// &amp;lt;summary&amp;gt;&lt;br /&gt;   /// See generic implementation of &amp;lt;see cref="GetEnumerator"/&amp;gt;.&lt;br /&gt;   /// &amp;lt;/summary&amp;gt;&lt;br /&gt;   /// &amp;lt;returns&amp;gt;See generic implementation of &amp;lt;see cref="GetEnumerator"/&amp;gt;.&lt;br /&gt;   /// &amp;lt;/returns&amp;gt;&lt;br /&gt;   IEnumerator IEnumerable.GetEnumerator() {&lt;br /&gt;      return this.GetEnumerator();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can download the source file and the unit tests here:&lt;br /&gt;&lt;a href="http://sites.google.com/site/florianreischl/blogspot-files/RingBuffer.cs?attredirects=0&amp;d=1"&gt;RingBuffer.cs&lt;/a&gt;&lt;br /&gt;&lt;a href="http://sites.google.com/site/florianreischl/blogspot-files/RingBufferTest.cs?attredirects=0&amp;d=1"&gt;RingBufferTests.cs&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-2570733876826723226?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/2570733876826723226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2010/01/generic-c-ringbuffer.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/2570733876826723226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/2570733876826723226'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2010/01/generic-c-ringbuffer.html' title='Generic C# RingBuffer'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-8515961945062655866</id><published>2009-12-21T14:47:00.000-08:00</published><updated>2010-06-05T08:13:46.263-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>A Strange Kind of a Relational EDI</title><content type='html'>&lt;span class="text"&gt;&lt;br /&gt;Today I'll speak about a very different kind of data exchange. The following approach might sound strange for the first moment (it did to me!). However, after some days thinking about, I think this might be a new way which probably provides some powerful new solutions.&lt;br /&gt;&lt;br /&gt;First as first. Let's start up with a general discussion about different types and directions of EDIs (Electronic Data Interchange).&lt;br /&gt;&lt;br /&gt;Many of us work with EDIs to exchange data between different systems and/or locations. I think there are two main types of data interchange directions.&lt;br /&gt;&lt;br /&gt;The first direction of EDIs are data-loader routines or processes which load data from 3rd level applications. Especially todays EAI (Enterprise Application &lt;b&gt;Integration&lt;/b&gt;) applications are often related to many different other applications. This might be an order system which takes customer information from a CRM tool and some employee information from a HR-software. The important attribute here for this kind of data exchange is the communication with &lt;i&gt;other&lt;/i&gt; applications which are not part of your own project.&lt;br /&gt;&lt;br /&gt;The second kind of EDIs are synchronization routines or processes which are used to keep systems in sync. These processes are often used to exchange data between different servers (e.g. locations) of a distributed system. Another sample for sync routines is a offline support of a product catalog on a sales notebook. Last but not least synchronization processes are used for staging areas between operational and analysis systems like &lt;a href="http://www.microsoft.com/sqlserver/2008/en/us/Analysis-Services.aspx"&gt;SSAS&lt;/a&gt;. The important attribute of this kind of data exchange in this post is the communication between systems of &lt;b&gt;the same project&lt;/b&gt; or company.&lt;br /&gt;&lt;br /&gt;As you see, I want to point the difference of communication between &lt;i&gt;your own&lt;/i&gt; project modules and &lt;i&gt;external&lt;/i&gt; systems.&lt;br /&gt;&lt;br /&gt;Next we'll go on with a short listing of the most common available EDI formats and their strengths and weaknesses.&lt;br /&gt;&lt;/span&gt;&lt;h3&gt;An EDI Format Inventory&lt;/h3&gt;&lt;span class="text"&gt;Todays most common EDI formats seem to be CSV, XML. Sure there are several other - more specific - EDI formats like EDIFACT, BORD128, binary serialization and so forth. Though, for sake of brevity those formats are not scope of this post.&lt;br /&gt;&lt;/span&gt;&lt;h3&gt;CSV&lt;/h3&gt;&lt;span class="text"&gt;CSV files (separated by comma, tab, semicolon or whatever) are especially used to exchange huge amounts of data. The main strength of this format is its compactness. CSV files contain almost no overhead. The files are human readable with tools like Notepad (or any other text editor) or Excel. Especially data storage systems like SQL Server, many other RDBMSs or &lt;a href="http://msdn.microsoft.com/en-us/library/ms141026.aspx"&gt;SSIS&lt;/a&gt; provide build in functionality to write and read CSV files.&lt;br /&gt;&lt;br /&gt;On the other hand, CSV files have some weaknesses. First, the files are not relational, which means you cannot specify links between different kinds of data. Sure you can use distinct files for each object (or data) type and put everything together into an ZIP archive. Nevertheless, the files are not integrity checked. Another issue of CSV files is a missing search functionality. Microsofts OLEDB Jet-Provider enables simple SQL queries on CSV files but this is not a standard on other operational systems. Finally CSV files are not type safe. Your third column might be specified as an amount of goods, but you can never be sure that data in all rows are really stored in a decimal format and even if they are, you need to know the formatting information of the data. E.g. an amount of "1,234.56" in German format is "1.234,56". With date/time formats it becomes more &lt;i&gt;funny&lt;/i&gt; ;-)&lt;br /&gt;&lt;/span&gt;&lt;h3&gt;XML&lt;/h3&gt;&lt;span class="text"&gt;Over the last some years XML became more and more the most common format for almost any kind of data exchange. Why? Here just a subset of reasons...&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It supports references (links) between different objects. This could be direct parent-child relations or foreign-key like references to other XML-objects within or even without the current XML file.&lt;/li&gt;&lt;li&gt;With XPath it supports a full featured XML query language.&lt;/li&gt;&lt;li&gt;Almost all todays development kits provide build in XML support.&lt;/li&gt;&lt;li&gt;XML files can be validated via XSDs for data types, required and optional object properties and required relations.&lt;/li&gt;&lt;li&gt;It is human readable with any kind of text editor, web browsers and many IDEs.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;A common approach to use XML for data exchange is object serialization and there are two generally different ways to handle XML serialization. In smaller projects it often makes sense to directly serialize the existing &lt;a href="http://en.wikipedia.org/wiki/Domain_object"&gt;Domain Objects&lt;/a&gt;. In more complex domain models serialization is often done by creation of &lt;a href="http://en.wikipedia.org/wiki/Data_Transfer_Object"&gt;DTOs&lt;/a&gt;, since the domain model might be too complex and contain too much validation which might be not needed (or desired) while (de-)serialization. DTOs are a simplified and coarse grained simplified versions of fine grained domain objects.&lt;br /&gt;&lt;br /&gt;Sure, XML can also be used without any build in serialization methods. Since this slightly eliminates the "easy to use" factor, this is usually only needed for very large amounts of data or very flexible requirements.&lt;br /&gt;&lt;br /&gt;Independent of all the strength of XML, it also has some weaknesses which might be important for some requirements.&lt;br /&gt;&lt;br /&gt;XML is a very verbose data format. Though, this can be handled by using any kind of compression (like ZIP, GZip and so on).&lt;br /&gt;&lt;br /&gt;Another weakness of XML is XPath. Don't get me wrong, XPath is a powerful query language and I (almost) always get what I want. Nevertheless, most times original data storages are relational databases. When using XML you always have to either implement some kind of XPath based &lt;a href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;Mapper&lt;/a&gt; (when working with plain XML) or any object based way to find all de-serialized objects and their relations (when working with serialization).&lt;br /&gt;&lt;/span&gt;&lt;h3&gt;A Relational EDI&lt;/h3&gt;&lt;span class="text"&gt;Wouldn't it be cool to work with &lt;b&gt;SQL&lt;/b&gt; when working with EDI, eh? In my opinion, yes! So, why don't do this?&lt;br /&gt;&lt;br /&gt;Did you ever think about using embedded databases (like &lt;a href="http://www.microsoft.com/Sqlserver/2005/en/us/compact.aspx"&gt;SQL Server Compact&lt;/a&gt;, &lt;a href="http://www.sqlite.org/"&gt;SQLite&lt;/a&gt; or others)? Sounds strange to you? It did sound strange to me, too. However, who cares? After several days thinking about this approach, this appears to be a probably very new kind of data exchange.&lt;br /&gt;&lt;br /&gt;When you work with an O/R-Mapper you might even get this feature as a gift. Even if you don't work with an O/R-Mapper, most usual SQL statements are supported by those new embedded database systems. When working with SQL Server Compact you might think about using Microsofts &lt;a href="http://msdn.microsoft.com/en-us/library/cc281959.aspx"&gt;Sync Framework&lt;/a&gt; to load and update your data from your &lt;i&gt;"database interchange"&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Embedded databases support constraints primary keys, foreign keys, indexes (and some even more). Armed with these constraints, embedded databases provide a ensured relational integrity. You can also be sure that all your data are stored in correct format.&lt;br /&gt;&lt;br /&gt;One &lt;i&gt;potential&lt;/i&gt; issue of embedded databases is the file size. A new, empty SQL Server Compact database has a initial size of 20KB (for being empty :-D ). 20KB appear to be not too much for me, but what about file growing when data become loaded? After this initial size it grows less than XML files. I tried to create an XML and a SQL Server Compact database each containing all Customers (91 rows) and Orders (921 rows) from good old Northwind database. The XML file ended up with 437KB, the SQL Server Compact database ended up with 184KB (containing both primary keys and a foreign key from Orders to Customers). To be fair, I also tried to compress both resulting files with WinRAR. The XML file was compressed to 30KB, the database file was compressed to 31KB. Sure, "large" and "small" always depend on your environment, but in my opinion this compression appears to be okay.&lt;br /&gt;&lt;br /&gt;Is missing human readability an issue of embedded databases? I'd say, yes ant no. You cannot open the files with a text editor. But you can use tools like SSMS (in case of SQL Server Compact) or any other database query tool. If you work with an O/R-Mapper or any other &lt;a href="http://en.wikipedia.org/wiki/Data_access_layer"&gt;Data Access Layer&lt;/a&gt; which supports different database systems you can probably even use your tailor made business application to browse the data within the "interchange".&lt;br /&gt;&lt;br /&gt;Nevertheless, the most important issue of using embedded databases as EDI is the fact that it is completely &lt;b&gt;no standard&lt;/b&gt; today. For this reason this should only be used for in-project synchronization between different storages at the moment.&lt;br /&gt;&lt;/span&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;span class="text"&gt;If network traffic is one of the issues you fight with when exchanging EDIs between systems, CSV is definitely the way to go.&lt;br /&gt;&lt;br /&gt;If you need a standardized communication to any outside (of your project) module, XML is usually the way to go.&lt;br /&gt;&lt;br /&gt;If you have to synchronize larger amounts of data between different parts of your own system, you might think about using embedded databases doing this job. At least, give it a try or some hours to think about ;-).&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-8515961945062655866?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/8515961945062655866/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2009/12/strange-kind-of-relational-edi.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/8515961945062655866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/8515961945062655866'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2009/12/strange-kind-of-relational-edi.html' title='A Strange Kind of a Relational EDI'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-122240556416612836</id><published>2009-11-27T03:43:00.000-08:00</published><updated>2010-06-05T08:15:39.764-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><title type='text'>What's the Problem with List&lt;T&gt; Properties in BLL?</title><content type='html'>Today I'll speak about a practice for business logic layers (BLL).&lt;br /&gt;&lt;br /&gt;The .NET &lt;i&gt;List&amp;lt;T&amp;gt;&lt;/i&gt; is a nice and really handy class for in many destinations. However, this class is not the best solution for libraries like business logic layers (BLL) to provide related domain objects.&lt;br /&gt;&lt;br /&gt;Above a very simple part of a fictive business logic layer (BLL).&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;class Order {&lt;br /&gt;   public int Id { get; set; }&lt;br /&gt;   // ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Customer {&lt;br /&gt;   public int Id { get; set; }&lt;br /&gt;   public List&amp;lt;Order&amp;gt; Orders { get; private set; }&lt;br /&gt;   // ...&lt;br /&gt;   internal void SetOrders(List&amp;lt;Order&amp;gt; orders) {&lt;br /&gt;      this.Orders = orders;&lt;br /&gt;   }&lt;br /&gt;   // ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span class="text"&gt;Using the &lt;i&gt;List&amp;lt;Order&amp;gt;&lt;/i&gt; in this solution can cause some problems.&lt;/span&gt;&lt;h3&gt;Lacy Loading&lt;/h3&gt;&lt;span class="text"&gt;You should always try to load all information needed for a specific business case. Though, there are reasons why this makes no sense. For instance if the don't know which related data are needed when you start your business transaction. Another reason might be a too huge count of related objects. Here is lazy loading a nice pattern.&lt;br /&gt;&lt;br /&gt;In our fictive layer, there are cases when we need the orders of our customer, but there might be several other cases when we don't need the related orders. You can use a &lt;a href="http://en.wikipedia.org/wiki/Builder_pattern"&gt;Builder&lt;/a&gt; to compose different customers for different business cases. However, sometimes the required relations to handle a business case are not clear when the business transaction starts.&lt;br /&gt;&lt;br /&gt;Always to load too much information might become a performance problem. Lazy loading is a nice practice (when it is used correct) to ensure related information &lt;i&gt;if they are needed&lt;/i&gt;. One way to handle lazy loading is AOP but sometimes you can end up in a &lt;i&gt;ripple loading&lt;/i&gt;. For instance, if you have to handle thousand customers and their orders it makes more sense to load all (or a page of 100) orders in one database query. In this case you might prefer a special implementation which handles this loading.&lt;/span&gt;&lt;h3&gt;Validation&lt;/h3&gt;&lt;span class="text"&gt;You can derive from &lt;i&gt;List&amp;lt;T&amp;gt;&lt;/i&gt; but it does not provide any way to validate the &lt;i&gt;Order&lt;/i&gt; which become accessed/removed/added. Probably you want to validate newly added orders to ensure they are valid and/or not yet attached to any customer. What about deletion? It should not be possible to delete an order which is already billed. For these business cases, you need an observable list or a read-only list.&lt;/span&gt;&lt;br /&gt;&lt;h3&gt;Presentation&lt;/h3&gt;&lt;span class="text"&gt;This very depends on how flexible your BLL wants to be but think about your presentation layer. If you want to be able to bind your orders list to a data bindable control like the .NET &lt;i&gt;DataGridView&lt;/i&gt;. The &lt;i&gt;List&amp;lt;T&amp;gt;&lt;/i&gt; does not provide all required methods to enable add/remove handling for the grid.&lt;br /&gt;&lt;br /&gt;Notice, I do &lt;b&gt;not&lt;/b&gt; speak about any coupling between business and presentation layer but it might be neat if your BLL provides some binable objects which can be reused in win-, wpf- and/or web-applications.&lt;/span&gt;&lt;br /&gt;&lt;h3&gt;Custom Behavior&lt;/h3&gt;&lt;span class="text"&gt;As a last reason for now (there might be more) why List&amp;lt;T&amp;gt; should not be used here is customization of behavior. Probably your list needs to be sorted by any order information. Maybe you need an observer list which organizes this sorting, even if you change one or more of the contained orders.&lt;/span&gt;&lt;br /&gt;&lt;h3&gt;Better Solution&lt;/h3&gt;&lt;span class="text"&gt;A better approach to provide related 0...* objects is usually the &lt;i&gt;&lt;b&gt;I&lt;/b&gt;List&amp;lt;T&amp;gt;&lt;/i&gt; &lt;b&gt;interface&lt;/b&gt;. This interface provides (almost) all methods which are available by using &lt;i&gt;List&amp;lt;T&amp;gt;&lt;/i&gt; but it provides a very low coupled representation of the &lt;i&gt;Order&lt;/i&gt; property. Feel free to use &lt;i&gt;List&amp;lt;T&amp;gt;&lt;/i&gt; for common initialization within your BLL. If you ever need a special handling you are able to provide another list though.&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;class Customer {&lt;br /&gt;   public int Id { get; set; }&lt;br /&gt;   public IList&amp;lt;Order&amp;gt; Orders { get; private set; }&lt;br /&gt;   // ...&lt;br /&gt;   internal void SetOrders(IList&amp;lt;Order&amp;gt; orders) {&lt;br /&gt;      this.Orders = orders;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span class="text"&gt;Another solution is to provide a completely custom list interface or base class (I always prefer interfaces). This also works fine and keeps you able to provide different lists with different behavior. Though, this has a larger startup cost for your project. IMO &lt;i&gt;IList&amp;lt;T&amp;gt;&lt;/i&gt; fits fine for most consumers of a BLL.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-122240556416612836?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/122240556416612836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2009/11/whats-problem-with-list-properties-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/122240556416612836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/122240556416612836'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2009/11/whats-problem-with-list-properties-in.html' title='What&apos;s the Problem with List&amp;lt;T&amp;gt; Properties in BLL?'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-7195054486141532951</id><published>2009-11-16T14:47:00.000-08:00</published><updated>2011-09-10T12:07:35.390-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Table-Valued Parameters - A Performance Comparison</title><content type='html'>As I wrote in some of my previous posts, table-valued parameters - which have been introduced with SQL Server 2008 - appear to be a great feature to enable client side bulk operations when working with SQL Server. They enable client data provider like ADO.NET to send a complete set of data to the server instead of calling serveral single row operations. Today we'll do some comparsions.&lt;br /&gt;&lt;br /&gt;I'll start with a &lt;del&gt;short&lt;/del&gt; (had to correct this...) description of the test environment. To use the best possible performance for both ways I'll use stored procedures.&lt;br /&gt;&lt;br /&gt;The first test results focus the performance of single statements vs. bulk operations in a single client environemnt - means without any other concurrent activities. The second, more important tests cover a performance comparsion in a multi-client scenario. The last part will show a comparison for some larger bulk operations.&lt;br /&gt;&lt;br/&gt;&lt;h3&gt;Test Environment&lt;/h3&gt;If you already read my previous posts you can skip this section. I try to keep this post uncoupled from my previous post since this covers another general topic (TVPs). So I have to repreat the test environment and the general way to use table-valued parameters from ADO.NET.&lt;br /&gt;&lt;br /&gt;For my tests I'll used the following simple table to INSERT/UPDATE rows.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: sql;"&gt;CREATE TABLE TestMany&lt;br /&gt;(&lt;br /&gt;   Id int IDENTITY(1,1) NOT NULL&lt;br /&gt;      PRIMARY KEY CLUSTERED &lt;br /&gt;   ,SomeInt int NULL&lt;br /&gt;   ,SomeDate datetime NULL&lt;br /&gt;   ,SomeText varchar(100) NULL,&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;span class="text"&gt;Whenever we intend to use table-valued parameters in SQL Server 2008, we need a table-valued type defined in SQL Server which can be used as a collection of Data Transfer Objects (DTOs) to transfer .NET native data to SQL Server.&lt;br /&gt;&lt;/span&gt;&lt;pre class="brush: sql;"&gt;CREATE TYPE TestManyMergeType AS TABLE(&lt;br /&gt;   Id int NOT NULL&lt;br /&gt;   ,Action char(1) NOT NULL&lt;br /&gt;      CHECK (Action IN ('I', 'D', 'U'))&lt;br /&gt;   ,SomeInt int NULL&lt;br /&gt;   ,SomeDate datetime NULL&lt;br /&gt;   ,SomeText varchar(100) NULL&lt;br /&gt;   &lt;br /&gt;   ,PRIMARY KEY CLUSTERED &lt;br /&gt;      (Id, Action)&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;span class="text"&gt;This type covers our destination table with some slight exceptions. Since we will use table-valued parameters to push all changed client data in one package to SQL Server, we need a column which tells SS2k8 how to handle a distinct row. Therefore, we'll use the &lt;i&gt;Action&lt;/i&gt; column which specifies the current row to be &lt;b&gt;I&lt;/b&gt;nserted, &lt;b&gt;U&lt;/b&gt;pdated or &lt;b&gt;D&lt;/b&gt;eleted. We don't use an &lt;i&gt;IDENTITY&lt;/i&gt; specification for our "Id" column since we need to be able to specify an destination "Id" to be handled. To insert new rows we can use negative, unique "Id" values which are required to map newly inserted rows on client-side to their new server ids. To get the best selectivity we use a primary key over the "Id" and "Action" columns.&lt;br /&gt;&lt;br /&gt;To provide a stored procedure which gets a table-valued parameter, the parameter has to be specified as READONLY in SS2k8.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: sql;"&gt;CREATE PROCEDURE SaveTestMany&lt;br /&gt;   @data TestManyMergeType READONLY&lt;br /&gt;AS&lt;br /&gt;   SET NOCOUNT ON;&lt;br /&gt;   &lt;br /&gt;   -- update&lt;br /&gt;   UPDATE trg SET &lt;br /&gt;         SomeInt = src.SomeInt&lt;br /&gt;         ,SomeDate = src.SomeDate&lt;br /&gt;         ,SomeText = src.SomeText&lt;br /&gt;      FROM TestMany trg &lt;br /&gt;         JOIN @data src &lt;br /&gt;         ON trg.Id = src.Id AND src.Action = 'U';&lt;br /&gt;&lt;br /&gt;   -- insert&lt;br /&gt;   INSERT INTO TestMany&lt;br /&gt;      SELECT SomeInt,SomeDate,SomeText &lt;br /&gt;      FROM @data &lt;br /&gt;      WHERE Action = 'I' &lt;br /&gt;      ORDER BY Id&lt;br /&gt;&lt;br /&gt;   -- return last IDENTITY and count of added rows&lt;br /&gt;   SELECT SCOPE_IDENTITY(), @@ROWCOUNT;&lt;br /&gt;GO&lt;br /&gt;&lt;/pre&gt;&lt;span class="text"&gt;The important most important part of this procedure is the ORDER BY clause in the INSERT statement. This ensures that we can use the information about the last generated identity value (by &lt;i&gt;SCOPE_IDENTITY()&lt;/i&gt;) and the count of inserted rows (by &lt;i&gt;@@ROWCOUNT&lt;/i&gt;) to map the provided surrogate ids to the generated server ids. Maybe you think this might be dangerous without a MAXDOP option or anything else and maybe you are right, I just can tell you that I tried different order conditions and all rows have always been inserted in an exact order. So feel free to trust this or not. If you don't trust it (what is a good thing) do your own tests (what is a good thing, too) or just feel free to leave this post (what would be a really bad thing).&lt;br /&gt;&lt;br /&gt;To provide a table-valued parameter to a stored procedure from ADO.NET you have two possibilities. You can either provide your data by passing a &lt;i&gt;System.Data.DataTable&lt;/i&gt; (which appears be too blown just to provide simple data records in my opinion) or a custom implementation of an &lt;i&gt;IEnumerable&amp;lt;SqlDataRecord&amp;gt;&lt;/i&gt;. I'll use the enumerator in my tests since it is way faster and does not require to copy all domain objects into a data table.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: c-sharp;"&gt;class TestManyEnumerator : IEnumerable&amp;lt;SqlDataRecord&amp;gt;&lt;br /&gt;{&lt;br /&gt;   public TestManyEnumerator(IEnumerable&amp;lt;TestMany&amp;gt; data) {&lt;br /&gt;      _data = data;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private IEnumerable&amp;lt;TestMany&amp;gt; _data;&lt;br /&gt;&lt;br /&gt;   public IEnumerator&amp;lt;SqlDataRecord&amp;gt; GetEnumerator() {&lt;br /&gt;      SqlMetaData[] metaData = {&lt;br /&gt;         new SqlMetaData("Id", SqlDbType.Int),&lt;br /&gt;         new SqlMetaData("MergeAction", SqlDbType.Char, 1),&lt;br /&gt;         new SqlMetaData("SomeInt", SqlDbType.Int),&lt;br /&gt;         new SqlMetaData("SomeDate", SqlDbType.DateTime),&lt;br /&gt;         new SqlMetaData("SomeText", SqlDbType.VarChar, 100),&lt;br /&gt;      };&lt;br /&gt;&lt;br /&gt;      foreach (var item in _data) {&lt;br /&gt;         SqlDataRecord record = new SqlDataRecord(metaData);&lt;br /&gt;&lt;br /&gt;         record.SetValue(0, item.Id);&lt;br /&gt;         record.SetValue(1, item.ChangeState);&lt;br /&gt;         record.SetValue(2, item.SomeInt);&lt;br /&gt;         record.SetValue(3, item.SomeDate);&lt;br /&gt;         record.SetValue(4, item.SomeText);&lt;br /&gt;&lt;br /&gt;         yield return record;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {&lt;br /&gt;      return this.GetEnumerator();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span class="text"&gt;This enumerator handles domain objects from type &lt;i&gt;TestMany&lt;/i&gt; which map exactly to our above specified table-valued T-SQL type. &lt;i&gt;ChangeState&lt;/i&gt; specifies the state ('I', 'D', 'U') of a particular object.&lt;br /&gt;&lt;br /&gt;To call our procedure with a set of data to be updated we have to specify a &lt;i&gt;SqlParameter&lt;/i&gt; with &lt;i&gt;SqlDbType.Structured&lt;/i&gt;, the name of the destination table-valued type as &lt;i&gt;TypeName&lt;/i&gt; and provide the previous enumerator as &lt;i&gt;Value&lt;/i&gt;.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: c-sharp;"&gt;using (SqlConnection cn = GetConnection(true))&lt;br /&gt;using (SqlTransaction tran = cn.BeginTransaction()) {&lt;br /&gt;   // get test data&lt;br /&gt;   IList&amp;lt;TestMany&amp;gt; data = GetTestData();&lt;br /&gt;&lt;br /&gt;   // create a new command as stored procedure&lt;br /&gt;   SqlCommand cmd = new SqlCommand("MergeTestMany", cn);&lt;br /&gt;   cmd.CommandType = CommandType.StoredProcedure;&lt;br /&gt;   cmd.Transaction = tran;&lt;br /&gt;   // create a new parameter ("Structured" defines a TVP)&lt;br /&gt;   SqlParameter p = cmd.Parameters.Add("@data", SqlDbType.Structured);&lt;br /&gt;   // specify the name of the TVP&lt;br /&gt;   p.TypeName = "TestManyMergeType";&lt;br /&gt;   p.Value = new TestManyEnumerator(data);&lt;br /&gt;&lt;br /&gt;   // catch the returned IDENTITY information&lt;br /&gt;   using (SqlDataReader reader = cmd.ExecuteReader()) {&lt;br /&gt;      reader.Read();&lt;br /&gt;      int lastId = reader.IsDBNull(0) ? -1 : (int)reader.GetDecimal(0);&lt;br /&gt;      int count = reader.GetInt32(1);&lt;br /&gt;      // synchronize all newly added keys&lt;br /&gt;      SyncAddedIds(data, count, lastId);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   tran.Commit();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span class="text"&gt;For a more detailed explanatin and the implementation of &lt;i&gt;GetTestData():IList&amp;lt;TestMany&amp;gt;&lt;/i&gt; and &lt;i&gt;GetConnection(open):SqlConnection&lt;/i&gt; please have a look &lt;a href="http://florianreischl.blogspot.com/2009/11/sql-server-and-bulk-data-persistence.html"&gt;here&lt;/a&gt;. For a generic approach, have a look at &lt;a href="http://florianreischl.blogspot.com/2009/11/generic-bdp-approach-for-sql-server.html"&gt;A Generic BDP Approach for SQL Server 2008&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The procedures to insert single rows into our &lt;i&gt;TestMany&lt;/i&gt; table are just simple as they can be.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: sql;"&gt;CREATE PROCEDURE [dbo].[InsertOneTestMany]&lt;br /&gt;   @id INT OUTPUT&lt;br /&gt;   ,@someInt INT&lt;br /&gt;   ,@someDate DATETIME&lt;br /&gt;   ,@someText VARCHAR(100)&lt;br /&gt;AS&lt;br /&gt;   SET NOCOUNT ON;&lt;br /&gt;   &lt;br /&gt;   INSERT INTO TestMany (SomeInt, SomeDate, SomeText)&lt;br /&gt;      SELECT @someInt, @someDate, @someText;&lt;br /&gt;   &lt;br /&gt;   SELECT @id = SCOPE_IDENTITY();&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;CREATE PROCEDURE [dbo].[UpdateOneTestMany]&lt;br /&gt;   @id INT&lt;br /&gt;   ,@someInt INT&lt;br /&gt;   ,@someDate DATETIME&lt;br /&gt;   ,@someText VARCHAR(100)&lt;br /&gt;AS&lt;br /&gt;   SET NOCOUNT ON;&lt;br /&gt;   &lt;br /&gt;   UPDATE TestMany SET &lt;br /&gt;         SomeInt = @someInt&lt;br /&gt;         ,SomeDate = @someDate&lt;br /&gt;         ,SomeText = @someText&lt;br /&gt;      WHERE Id = @id;&lt;br /&gt;GO&lt;br /&gt;&lt;/pre&gt;&lt;span class="text"&gt;I think there is nothing which needs to be explained.&lt;br /&gt;&lt;br /&gt;We're done with our test enviroment.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;h3&gt;Not part of this Post&lt;/h3&gt;&lt;span class="text"&gt;Calling a single statement procedure from .NET straight forward and part of many tutorials. Therefore I kept this source code away from here. I also don't show how to use multi-threading to call the above procedures in a concurrency scenario. &lt;br /&gt;&lt;br /&gt;I kept DELETE operations out of the party since they are often done by special purge processes instead of usual business applications.&lt;br /&gt;&lt;br /&gt;Since I don't have a home network, I did my tests with a SQL Server running on a VM on my local host. Therefore I cannot show you any comparison differences depending on network latency. &lt;br /&gt;&lt;/span&gt;&lt;br/&gt;&lt;h3&gt;Single Client Tests&lt;/h3&gt;&lt;span class="text"&gt;Let's compare the performance of single INSERT/UPDATE statements vs. bulk operations when using a single client connection. To get (almost) linear test results I executed each test configuration 1,000 times. One &lt;b&gt;important&lt;/b&gt; thing is that I always called the specified count of &lt;i&gt;INSERT&lt;/i&gt; &lt;b&gt;and&lt;/b&gt; &lt;i&gt;UPDATE&lt;/i&gt; operations in one round trip. So, "Count Insert/Update" with value "1" calls one &lt;i&gt;INSERT&lt;/i&gt; &lt;b&gt;and&lt;/b&gt; one &lt;i&gt;UPDATE&lt;/i&gt; operation, count "50" affects hundred rows. I did my tests with a destination table with just 100,000 rows and witha a table with 10,000,000 rows. Both table have been recreated after/before each test configuration and flushed by calling "&lt;i&gt;DBCC DROPCLEANBUFFERS() WITH NO_INFOMSGS;&lt;/i&gt;". To ensure as many index read operations as possible I arranged all operations over the complete complete id range of the table.&lt;br /&gt;&lt;br /&gt;Duration on a destination table with 100,000 rows after 1,000 executions.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table class="results_table" cellspacing="0px"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style="border-bottom: 0"&gt;Insert/Update&lt;/th&gt;&lt;th colspan="2" style="border-bottom: 0"&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Single Statements&lt;/th&gt;&lt;th&gt;Bulk Operation&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td class="good_td"&gt;1,299 ms&lt;/td&gt;&lt;td&gt;3,285 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td class="good_td"&gt;2,319 ms&lt;/td&gt;&lt;td&gt;2,995 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;3,201 ms&lt;/td&gt;&lt;td class="good_td"&gt;3,007 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;5,553 ms&lt;/td&gt;&lt;td class="good_td"&gt;3,121 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;11,923 ms&lt;/td&gt;&lt;td class="good_td"&gt;3,449 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;50&lt;/td&gt;&lt;td&gt;27,644 ms&lt;/td&gt;&lt;td class="good_td"&gt;4,769 ms&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;span class="text"&gt;Duration on a destination table with 10,000,000 rows after 1,000 executions.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table class="results_table" cellspacing="0px"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style="border-bottom: 0"&gt;Insert/Update&lt;/th&gt;&lt;th colspan="2" style="border-bottom: 0"&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Single Statements&lt;/th&gt;&lt;th&gt;Bulk Operation&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td class="good_td"&gt;2,631 ms&lt;/td&gt;&lt;td&gt;4,076 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td class="good_td"&gt;3,614 ms&lt;/td&gt;&lt;td&gt;4,200 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;4,608 ms&lt;/td&gt;&lt;td class="good_td"&gt;4,470 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;7,541 ms&lt;/td&gt;&lt;td class="good_td"&gt;4,381 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;12,308 ms&lt;/td&gt;&lt;td class="good_td"&gt;4,846 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;50&lt;/td&gt;&lt;td&gt;26,173 ms&lt;/td&gt;&lt;td class="good_td"&gt;6,336 ms&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span class="text"&gt;As you can see, there is a point at about five &lt;i&gt;INSERT/UPDATE&lt;/i&gt; operations (means 10 rows!) in one single transaction. With less than ten operations for the same table single statements are faster than bulk operations with table-valued parameters. If we hit this count of rows to be changed, table-valued parameters become way faster than classical single row operations.&lt;br /&gt;&lt;br /&gt;A work load between one and fifty INSERT and UPDATE tasks shows that single row operations take about 10 times longer (what's a good thing), the duration of bulk operations increase only about 1.5 times (what appears to be a better thing ;-) ).&lt;br /&gt;&lt;/span&gt;&lt;br/&gt;&lt;h3&gt;Multi-Client Tests&lt;/h3&gt;&lt;span class="text"&gt;As initially written. SS2k8 is a server and no &lt;i&gt;geeky&lt;/i&gt; feature has any worth if it works only in a single-client scenario. Therefore, now we'll have a look at some multi-client tests.&lt;br /&gt;&lt;br /&gt;Since concurrent executions take more time I ran the following tests only 100 times. I also changed the count of rows within the destination table to 500,000 what was a convenient value to arrange the threads over the whole table - to get the highest count of reads).&lt;br /&gt;&lt;br /&gt;The following results show the overall duration of 100 executions.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table class="results_table" cellspacing="0px"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style="border-bottom: 0"&gt;Insert/Update&lt;/th&gt;&lt;th colspan="2" style="border-bottom: 0"&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Single Statements&lt;/th&gt;&lt;th&gt;Bulk Operation&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th class="subtitle_th" colspan="3"&gt;1 Thread&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td class="good_td"&gt;159 ms&lt;/td&gt;&lt;td&gt;298 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td class="good_td"&gt;237 ms&lt;/td&gt;&lt;td&gt;358 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td class="good_td"&gt;344 ms&lt;/td&gt;&lt;td&gt;371 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;562 ms&lt;/td&gt;&lt;td class="good_td"&gt;391 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;1,040 ms&lt;/td&gt;&lt;td class="good_td"&gt;427 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;50&lt;/td&gt;&lt;td&gt;2457 ms&lt;/td&gt;&lt;td class="good_td"&gt;558 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th class="subtitle_th" colspan="3"&gt;2 Threads&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;387 ms&lt;/td&gt;&lt;td class="good_td"&gt;348 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;679 ms&lt;/td&gt;&lt;td class="good_td"&gt;368 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;854 ms&lt;/td&gt;&lt;td class="good_td"&gt;438 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;1,597 ms&lt;/td&gt;&lt;td class="good_td"&gt;421 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;3,513 ms&lt;/td&gt;&lt;td class="good_td"&gt;575 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;50&lt;/td&gt;&lt;td&gt;6,839 ms&lt;/td&gt;&lt;td class="good_td"&gt;830 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th class="subtitle_th" colspan="3"&gt;5 Threads&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1,466 ms&lt;/td&gt;&lt;td class="good_td"&gt;936 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;2,528 ms&lt;/td&gt;&lt;td class="good_td"&gt;943 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;3,542 ms&lt;/td&gt;&lt;td class="good_td"&gt;1,007 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;5,837 ms&lt;/td&gt;&lt;td class="good_td"&gt;1,097 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;10,995 ms&lt;/td&gt;&lt;td class="good_td"&gt;1,293 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;50&lt;/td&gt;&lt;td&gt;26,092 ms&lt;/td&gt;&lt;td class="good_td"&gt;2,251 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th class="subtitle_th" colspan="3"&gt;10 Threads&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;4,820 ms&lt;/td&gt;&lt;td class="good_td"&gt;1,604 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;13,290 ms&lt;/td&gt;&lt;td class="good_td"&gt;1,936 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;12,624 ms&lt;/td&gt;&lt;td class="good_td"&gt;1,838 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;28,829 ms&lt;/td&gt;&lt;td class="good_td"&gt;2,012 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;45,414 ms&lt;/td&gt;&lt;td class="good_td"&gt;2,789 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;50&lt;/td&gt;&lt;td&gt;97,498 ms&lt;/td&gt;&lt;td class="good_td"&gt;4,610 ms&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;span class="text"&gt;Again, remember "1" INSERT/UPDATE means &lt;b&gt;two&lt;/b&gt; operations within one transaction. Since single row operations usually scale almost linear they are still the faster solution for &lt;b&gt;single&lt;/b&gt; operations. However, as we see bulk operations using with table-valued parameters perform really fine in a multi-threaded environment.&lt;br /&gt;&lt;/span&gt;&lt;br/&gt;&lt;h3&gt;Some Larger Bulks&lt;/h3&gt;&lt;span class="text"&gt;Okay, we speak about &lt;b&gt;bulk&lt;/b&gt; operations so finally, let's do some real bulk operations.&lt;br /&gt;&lt;br /&gt;The following results show the complete duration of 10 executions.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table class="results_table" cellspacing="0px"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style="border-bottom: 0"&gt;Insert/Update&lt;/th&gt;&lt;th colspan="2" style="border-bottom: 0"&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Single Statements&lt;/th&gt;&lt;th&gt;Bulk Operation&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1,000&lt;/td&gt;&lt;td&gt;4,845 ms&lt;/td&gt;&lt;td class="good_td"&gt;370 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5,000&lt;/td&gt;&lt;td&gt;23,190 ms&lt;/td&gt;&lt;td class="good_td"&gt;2,033 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10,000&lt;/td&gt;&lt;td&gt;46,539 ms&lt;/td&gt;&lt;td class="good_td"&gt;4,854 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20,000&lt;/td&gt;&lt;td&gt;95,086 ms&lt;/td&gt;&lt;td class="good_td"&gt;7,209 ms&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;span class="text"&gt;In my opinion &lt;b&gt;400,000&lt;/b&gt; changed rows (remember we did 20,000 INSERT &lt;b&gt;and&lt;/b&gt; UPDATE operations and we executed 10 times!) in 7 seconds appear to be a really great performance. ;-)&lt;br /&gt;&lt;/span&gt;&lt;br/&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;span class="text"&gt;Apparently table-valued parameters might be a great feature for systems which work with bulk data manipulation. This might be some web or rich client applications but especially backend processes like data loader or synchronization processes. &lt;br /&gt;&lt;br /&gt;What does this mean? Probably nothing for a general statement. If you think bulk operations with table-valued parameters might be a nice feature for your project. Always do your own tests! We did no tests with a real network and we did not test &lt;i&gt;DELETE&lt;/i&gt; operations. &lt;br /&gt;&lt;br /&gt;As a general advice, always try to stay innovative but validate &lt;b&gt;everything&lt;/b&gt;. My intention was not to show you that you have to change all your running code, but to think about some new features which might be helpful.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-7195054486141532951?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/7195054486141532951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2009/11/table-valued-parametes-performance.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7195054486141532951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7195054486141532951'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2009/11/table-valued-parametes-performance.html' title='Table-Valued Parameters - A Performance Comparison'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-7786956875591528085</id><published>2009-11-14T04:41:00.000-08:00</published><updated>2010-06-05T08:29:27.370-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>A Generic BDP Approach for SQL Server 2008</title><content type='html'>As I promised in my previous post (&lt;a href="http://florianreischl.blogspot.com/2009/11/sql-server-and-bulk-data-persistence.html"&gt;SQL Server and Bulk Data Persistence (BDP)&lt;/a&gt;, today I'll show a possible generic approach of how to integrate &lt;a href="http://florianreischl.blogspot.com/2009/11/bulk-data-persistence-pattern.html"&gt;Bulk Data Persistence&lt;/a&gt; without writing a new enumerator for each domain object. In addition we will encapsulate the ID synchronization into a small framework.&lt;br /&gt;&lt;br /&gt;If you did not yet read the previous posts, please read it before you goon here. I see you as a person who knows the idea of BDP and how to handle it with SQL Server 2008.&lt;h3&gt;Our Task List&lt;/h3&gt;Let's reflect the steps of the previous post to figure out all tasks which have to be done:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;We have to provide &lt;i&gt;SqlMetaData&lt;/i&gt; objects to map our domain object properties&lt;/li&gt;&lt;li&gt;We have to provide an enumerator through the objects and create a &lt;i&gt;SqlDataRecord&lt;/i&gt;&lt;/li&gt;&lt;li&gt;We have to call some T-SQL to do the persistence&lt;/li&gt;&lt;li&gt;We have to map all the new server ids to our domain objects&lt;/li&gt;&lt;/ul&gt;Sounds &lt;b&gt;really complicated&lt;/b&gt;? It's not as hard as it sounds. It's more complicated than a command or simple strategy pattern but not much more than a usual Unit of Work pattern.&lt;br /&gt;&lt;h3&gt;ObjectState Enumeration&lt;/h3&gt;Before we start with our tasks, we have to change a dirty non-OO cheat we previously used. We change the "pseudo enum" to represent the state of a domain object to a real enum &lt;i&gt;ObjectState&lt;/i&gt;.&lt;br /&gt;&lt;pre class="brush: c-sharp;"&gt;public enum ObjectState&lt;br /&gt;{&lt;br /&gt;   Added,&lt;br /&gt;   Deleted,&lt;br /&gt;   Changed,&lt;br /&gt;   Unchanged,&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Okay, back to our task list...&lt;br /&gt;&lt;h3&gt;Column Mapping&lt;/h3&gt;The next thing we need is a general class to map the properties of a domain object into a &lt;i&gt;SqlMetaData&lt;/i&gt; object. Above we can see a possible &lt;i&gt;SqlMergeColumn&amp;lt;T&amp;gt;&lt;/i&gt; class which represents all information which are generally needed to create the meta data objects.&lt;pre class="brush: c-sharp;"&gt;&lt;br /&gt;class SqlMergeColumn&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt;   internal SqlMergeColumn(string columnName, SqlDbType sqlType,&lt;br /&gt;                           Func&amp;lt;T, object&amp;gt; getData) {&lt;br /&gt;      ColumnName = columnName;&lt;br /&gt;      SqlType = sqlType;&lt;br /&gt;      _getData = getData;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // callback to get the value from a current item&lt;br /&gt;   Func&amp;lt;T, object&amp;gt; _getData;&lt;br /&gt;   &lt;br /&gt;   public string ColumnName { get; private set; }&lt;br /&gt;   public SqlDbType SqlType { get; private set; }&lt;br /&gt;   public int MaxLength { get; internal set; }&lt;br /&gt;   public byte Precision { get; internal set; }&lt;br /&gt;   public byte Scale { get; internal set; }&lt;br /&gt;&lt;br /&gt;   public virtual object GetData(T item) {&lt;br /&gt;      // get the field value or DBNull&lt;br /&gt;      return _getData(item) ?? DBNull.Value;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public SqlMetaData GetMetaData() {&lt;br /&gt;      // get meta data for this property mapping&lt;br /&gt;      if (MaxLength != 0)&lt;br /&gt;         return new SqlMetaData(ColumnName, SqlType, MaxLength);&lt;br /&gt;      if (Precision != 0)&lt;br /&gt;         return new SqlMetaData(ColumnName, SqlType, Precision, Scale);&lt;br /&gt;      return new SqlMetaData(ColumnName, SqlType);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;As you see, the larger part of the class is a simple representation of properties which are needed to create a &lt;i&gt;SqlMetaData&lt;/i&gt; object. The &lt;i&gt;MaxLength&lt;/i&gt; property is needed for data types with variable length like text or binary data-types. The &lt;i&gt;Precision&lt;/i&gt; and &lt;i&gt;Scale&lt;/i&gt; properties are required for some numeric types like decimal.&lt;br /&gt;&lt;br /&gt;The &lt;i&gt; GetData(T):object&lt;/i&gt; method gets an object of generic type of the class. (I always try to avoid reflection if possible, since it is quiet slow and always hard do maintain.) The &lt;i&gt;GetData(T):object&lt;/i&gt; returns a value of the specified item by utilizing a delegate &lt;i&gt;Func&amp;lt;T,TReturn&amp;gt;&lt;/i&gt; which was provided by the constructor of the class.&lt;br /&gt;&lt;br /&gt;The last method &lt;i&gt;GetMetaData():SqlMetaData&lt;/i&gt; is a typical strategy method which returns the meta data for a &lt;i&gt;SqlDataRecord&lt;/i&gt; enumerator depending on the current configuration of an instance of the class.&lt;br /&gt;&lt;br /&gt;We have to handle two special column types. First, we need the identity column to be able to join data for UPDATE and DELETE and synchronize the server identity values with our newly added objects. Second, we need column which can tell us the type of the BDP action (add, change, delete) to be executed. To stay OO geeky we use two additional classes which inherit from &lt;i&gt;SqlMergeColumn&amp;lt;T&amp;gt;&lt;/i&gt;.&lt;pre class="brush: c-sharp;"&gt;&lt;br /&gt;// represents an identity merge column&lt;br /&gt;sealed class SqlMergeIdColumn&amp;lt;T&amp;gt; : SqlMergeColumn&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt;   public SqlMergeIdColumn(string columnName, Func&amp;lt;T, int&amp;gt; getIdData, &lt;br /&gt;                           Action&amp;lt;T, int&amp;gt; setIdData)&lt;br /&gt;      : base(columnName, SqlDbType.Int, (t) =&amp;gt; getIdData(t)) {&lt;br /&gt;      _setIdData = setIdData;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // private fields&lt;br /&gt;   Action&amp;lt;T, int&amp;gt; _setIdData;&lt;br /&gt;&lt;br /&gt;   public int GetIdData(T item) {&lt;br /&gt;      return (int)base.GetData(item);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void SetIdData(T item, int id) {&lt;br /&gt;      _setIdData(item, id);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// represents a merge action column&lt;br /&gt;sealed class SqlMergeActionColumn&amp;lt;T&amp;gt; : SqlMergeColumn&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt;   public SqlMergeActionColumn(string columnName, &lt;br /&gt;                               Func&amp;lt;T, ObjectState&amp;gt; getMergeAction)&lt;br /&gt;      : base(columnName, SqlDbType.Char, (t) =&amp;gt; getMergeAction(t)) {&lt;br /&gt;      MaxLength = 1;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public override object GetData(T item) {&lt;br /&gt;      switch (GetMergeAction(item)) {&lt;br /&gt;         case ObjectState.Added: return 'I';&lt;br /&gt;         case ObjectState.Changed: return 'U';&lt;br /&gt;         case ObjectState.Deleted: return 'D';&lt;br /&gt;         default: return 'X';&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public ObjectState GetMergeAction(T item) {&lt;br /&gt;      return (ObjectState)base.GetData(item);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The SqlMergeIdColumn&amp;lt;T&amp;gt; class provides two additional methods &lt;i&gt;GetIdValue(T):int&lt;/i&gt; to return an &lt;i&gt;System.Int32&lt;/i&gt; id value and &lt;i&gt;SetIdValue(T,int)&lt;/i&gt; to set a new id value after our database operation.&lt;br /&gt;&lt;br /&gt;The SqlMergeActionColumn&amp;lt;T&amp;gt; overwrites the &lt;i&gt;GetData(T):object&lt;/i&gt; method to transform the &lt;i&gt;ObjectState&lt;/i&gt; enum into a &lt;i&gt;System.Char&lt;/i&gt; for our data mapping.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;GetMergeAction(T):ObjectState&lt;/i&gt; returns the enum value of a specified domain object.&lt;br /&gt;&lt;br /&gt;Now, since we have column classes to specify a mapping to a table-valued parameter, we need a collection to store those mappings. I use a &lt;i&gt;System.Collections.ObjectModel.Collection&amp;lt;T&amp;gt;&lt;/i&gt; inherited collection in this sample.&lt;br /&gt;&lt;pre class="brush: c-sharp;"&gt;&lt;br /&gt;// represents a collection of SqlMergeColumn&amp;lt;T&amp;gt; objects&lt;br /&gt;sealed class SqlMergeColumnCollection&amp;lt;T&amp;gt;&lt;br /&gt;   : System.Collections.ObjectModel.Collection&amp;lt;SqlMergeColumn&amp;lt;T&amp;gt;&amp;gt;&lt;br /&gt;{&lt;br /&gt;   // add a data column&lt;br /&gt;   public void AddDataColumn(string columnName, SqlDbType sqlType,&lt;br /&gt;                             Func&amp;lt;T, object&amp;gt; getData) {&lt;br /&gt;      this.AddDataColumn(columnName, sqlType, 0, getData);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // add a data column&lt;br /&gt;   public void AddDataColumn(string columnName, SqlDbType sqlType,&lt;br /&gt;                             int maxLength, Func&amp;lt;T, object&amp;gt; getData) {&lt;br /&gt;      SqlMergeColumn&amp;lt;T&amp;gt; mapping = new SqlMergeColumn&amp;lt;T&amp;gt;(&lt;br /&gt;         columnName, sqlType, getData);&lt;br /&gt;      mapping.MaxLength = maxLength;&lt;br /&gt;      base.Add(mapping);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // add a data column&lt;br /&gt;   public void AddDataColumn(string columnName, SqlDbType sqlType,&lt;br /&gt;                             byte precision, byte scale, &lt;br /&gt;                             Func&amp;lt;T, object&amp;gt; getData) {&lt;br /&gt;      SqlMergeColumn&amp;lt;T&amp;gt; mapping = &lt;br /&gt;         new SqlMergeColumn&amp;lt;T&amp;gt;(columnName, sqlType, getData);&lt;br /&gt;      mapping.Precision = precision;&lt;br /&gt;      mapping.Scale = scale;&lt;br /&gt;      base.Add(mapping);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // set the id column&lt;br /&gt;   public void SetIdColumn(string columnName, &lt;br /&gt;                           Func&amp;lt;T, int&amp;gt; getIdData,&lt;br /&gt;                           Action&amp;lt;T, int&amp;gt; setIdData) {&lt;br /&gt;      base.Add(new SqlMergeIdColumn&amp;lt;T&amp;gt;(columnName, getIdData, setIdData));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // set the merge action column&lt;br /&gt;   public void SetMergeColumn(string columnName, &lt;br /&gt;                              Func&amp;lt;T, ObjectState&amp;gt; getMergeAction) {&lt;br /&gt;      base.Add(new SqlMergeActionColumn&amp;lt;T&amp;gt;(columnName, getMergeAction));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // get the id column&lt;br /&gt;   internal SqlMergeIdColumn&amp;lt;T&amp;gt; GetIdColumn() {&lt;br /&gt;      return this.OfType&amp;lt;SqlMergeIdColumn&amp;lt;T&amp;gt;&amp;gt;().First();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // get the merge column&lt;br /&gt;   internal SqlMergeActionColumn&amp;lt;T&amp;gt; GetMergeColumn() {&lt;br /&gt;      return this.OfType&amp;lt;SqlMergeActionColumn&amp;lt;T&amp;gt;&amp;gt;().First();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // get only the data columns&lt;br /&gt;   internal IEnumerable&amp;lt;SqlMergeColumn&amp;lt;T&amp;gt;&amp;gt; GetDataColumns() {&lt;br /&gt;      return this.Where(c =&amp;gt; c.GetType() == typeof(SqlMergeColumn&amp;lt;T&amp;gt;));&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;We've got three different implementations of &lt;i&gt;AddDataColumn&lt;/i&gt; to add usual data column mappings. In addition we've got two methods (&lt;i&gt;SetIdColumns&lt;/i&gt; and &lt;i&gt;SetMergeColumn&lt;/i&gt;) to specify the special id and merge-action columns. At last we have three methods (&lt;i&gt;GetIdColumn&lt;/i&gt;, &lt;i&gt;GetMergeColumn&lt;/i&gt; and &lt;i&gt;GetDataColumns&lt;/i&gt;) to access the different column types. I marked those methods as &lt;i&gt;internal&lt;/i&gt; since they are only needed within the BDP framework and usually not important for a consumer of the framework.&lt;br /&gt;&lt;br /&gt;Note, this framework is just a sample implementation. To keep it simple, I didn't add the possibility to specify the order of all columns. This means, currently all columns have to be specified in same order as defined in the table-valued type. Feel free to add an order parameter for all methods if you need this.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Data Enumerator&lt;/h3&gt;As we know, we have to provide a &lt;i&gt;IEnumerable&amp;lt;SqlDataRecord&amp;gt;&lt;/i&gt; as value of a .NET &lt;i&gt;SqlParameter&lt;/i&gt; which represents a table-valued parameter. The following listing shows a generic implementation of this class.&lt;br /&gt;&lt;pre class="brush: c-sharp;"&gt;sealed class Sql2k8MergeEnumerable&amp;lt;T&amp;gt; : IEnumerable&amp;lt;SqlDataRecord&amp;gt;&lt;br /&gt;{&lt;br /&gt;   // generic class to handle field access by lambda expression&lt;br /&gt;   // create a new enumerator&lt;br /&gt;   internal Sql2k8MergeEnumerable(IEnumerable&amp;lt;T&amp;gt; data, &lt;br /&gt;                                  SqlMergeColumnCollection&amp;lt;T&amp;gt; mappings) {&lt;br /&gt;      _data = data;&lt;br /&gt;      _mappings = mappings;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // private fields&lt;br /&gt;   IEnumerable&amp;lt;T&amp;gt; _data;&lt;br /&gt;   SqlMergeColumnCollection&amp;lt;T&amp;gt; _mappings;&lt;br /&gt;&lt;br /&gt;   // the enumerator which will be called from ADO.NET for a SqlParameter value&lt;br /&gt;   public IEnumerator&amp;lt;SqlDataRecord&amp;gt; GetEnumerator() {&lt;br /&gt;      // get all SqlMetaData for specified column mappings&lt;br /&gt;      SqlMetaData[] metaData =&lt;br /&gt;        _mappings.Select(mapping =&amp;gt; mapping.GetMetaData()).ToArray();&lt;br /&gt;&lt;br /&gt;      foreach (var item in _data) {&lt;br /&gt;         // create a new record&lt;br /&gt;         SqlDataRecord record = new SqlDataRecord(metaData);&lt;br /&gt;         // fill the record with its values&lt;br /&gt;         for (int i = 0; i &amp;lt; _mappings.Count; i++)&lt;br /&gt;            record.SetValue(i, _mappings[i].GetData(item));&lt;br /&gt;         // return the current record&lt;br /&gt;         yield return record;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   IEnumerator IEnumerable.GetEnumerator() {&lt;br /&gt;      return this.GetEnumerator();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The class gets the data to iterate through and an instance of our above implemented merge column collection.&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;GetEnumerator():IEnumerator&amp;lt;SqlDataRecord&amp;gt;&lt;/i&gt; method utilizes the column mappings collection to create the meta data objects we need for a data record. After this it iterates through all data and returns the data records. To fill the records it uses the &lt;i&gt;GetData&lt;/i&gt; method we already defined on our column classes.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Merge Command&lt;/h3&gt;A quick look back to our task list shows to missing tasks. We need something to generate the persisting T-SQL and we have to sync the client surrogate ids to the server side generated identity values. (I added both functionalities into one class, feel free to change this for a lower coupling.)&lt;br /&gt;&lt;pre class="brush: c-sharp;"&gt;&lt;br /&gt;class Sql2k8MergeCommand&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt;   public Sql2k8MergeCommand(string tableName, string tableTypeName, &lt;br /&gt;                             IEnumerable&amp;lt;T&amp;gt; data) {&lt;br /&gt;      _tableName = tableName;&lt;br /&gt;      _tableTypeName = tableTypeName;&lt;br /&gt;      _data = data;&lt;br /&gt;      Columns = new SqlMergeColumnCollection&amp;lt;T&amp;gt;();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // private fields&lt;br /&gt;   string _tableName;&lt;br /&gt;   string _tableTypeName;&lt;br /&gt;   IEnumerable&amp;lt;T&amp;gt; _data;&lt;br /&gt;&lt;br /&gt;   public SqlMergeColumnCollection&amp;lt;T&amp;gt; Columns { get; private set; }&lt;br /&gt;   public SqlConnection Connection { get; set; }&lt;br /&gt;   public SqlTransaction Transaction { get; set; }&lt;br /&gt;&lt;br /&gt;   // execute the merge command&lt;br /&gt;   public void Execute() {&lt;br /&gt;      // create an SqlCommand&lt;br /&gt;      SqlCommand cmd = new SqlCommand();&lt;br /&gt;      cmd.Connection = Connection;&lt;br /&gt;      cmd.Transaction = Transaction;&lt;br /&gt;      // get the dynamic SQL&lt;br /&gt;      cmd.CommandText = GetCommandText();&lt;br /&gt;      // create a parameter which gets all data as table-valued parameter&lt;br /&gt;      SqlParameter data = cmd.Parameters.Add("@data", SqlDbType.Structured);&lt;br /&gt;      data.TypeName = _tableTypeName;&lt;br /&gt;      data.Value = new Sql2k8MergeEnumerable&amp;lt;T&amp;gt;(_data, Columns);&lt;br /&gt;&lt;br /&gt;      // execute the command and read the IDENTITY and INSERT row count&lt;br /&gt;      using (SqlDataReader reader = cmd.ExecuteReader()) {&lt;br /&gt;         SyncSurrogateIds(reader);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // get the sql command text to be executed&lt;br /&gt;   private string GetCommandText() {&lt;br /&gt;      StringBuilder update = new StringBuilder(0x100);&lt;br /&gt;      StringBuilder insert = new StringBuilder(0x100);&lt;br /&gt;&lt;br /&gt;      // build columns for INSERT and UPDATE&lt;br /&gt;      foreach (var column in Columns.GetDataColumns()) {&lt;br /&gt;         insert.AppendFormat("{0},", column.ColumnName);&lt;br /&gt;         update.AppendFormat("trg.{0}=src.{0},", column.ColumnName);&lt;br /&gt;      }&lt;br /&gt;      // remove the trailing ","&lt;br /&gt;      insert.Remove(insert.Length - 1, 1);&lt;br /&gt;      update.Remove(update.Length - 1, 1);&lt;br /&gt;&lt;br /&gt;      string id = Columns.GetIdColumn().ColumnName;&lt;br /&gt;      string merge = Columns.GetMergeColumn().ColumnName;&lt;br /&gt;      StringWriter sql = new StringWriter(new StringBuilder(0x400));&lt;br /&gt;&lt;br /&gt;      // delete&lt;br /&gt;      sql.WriteLine("DELETE trg FROM {0} trg WHERE EXISTS (", _tableName);&lt;br /&gt;      sql.WriteLine("   SELECT * FROM @data src");&lt;br /&gt;      sql.WriteLine("   WHERE src.{0} = trg.{0} AND src.{1} = 'D');", &lt;br /&gt;         id, merge);&lt;br /&gt;      // update&lt;br /&gt;      sql.WriteLine("UPDATE trg SET {0} FROM {1} trg", update, _tableName);&lt;br /&gt;      sql.WriteLine("   JOIN @data src ON trg.{0} = src.{0} AND src.{1} = 'U';",&lt;br /&gt;         id, merge);&lt;br /&gt;      // insert&lt;br /&gt;      sql.WriteLine("INSERT INTO {0} ({1}) SELECT {1} FROM @data", &lt;br /&gt;         _tableName, insert);&lt;br /&gt;      sql.WriteLine("   WHERE {0} = 'I' ORDER BY {1};", merge, id);&lt;br /&gt;      // return identity information&lt;br /&gt;      sql.WriteLine("SELECT SCOPE_IDENTITY(), @@ROWCOUNT;");&lt;br /&gt;&lt;br /&gt;      return sql.ToString();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void SyncSurrogateIds(SqlDataReader reader) {&lt;br /&gt;      int lastId;&lt;br /&gt;      int count;&lt;br /&gt;&lt;br /&gt;      // get identity information from reader&lt;br /&gt;      reader.Read();&lt;br /&gt;      lastId = reader.IsDBNull(0) ? -1 : (int)reader.GetDecimal(0);&lt;br /&gt;      count = reader.GetInt32(1);&lt;br /&gt;      // no new rows added&lt;br /&gt;      if (count == 0)&lt;br /&gt;         return;&lt;br /&gt;      &lt;br /&gt;      SqlMergeActionColumn&amp;lt;T&amp;gt; mergeCol = Columns.GetMergeColumn();&lt;br /&gt;      SqlMergeIdColumn&amp;lt;T&amp;gt; idCol = Columns.GetIdColumn();&lt;br /&gt;      // get client surrogate ids&lt;br /&gt;      SortedList&amp;lt;int, T&amp;gt; idLookup = new SortedList&amp;lt;int, T&amp;gt;(count);&lt;br /&gt;      foreach (var item in _data)&lt;br /&gt;         if (mergeCol.GetMergeAction(item) == ObjectState.Added)&lt;br /&gt;            idLookup.Add(idCol.GetIdData(item), item);&lt;br /&gt;&lt;br /&gt;      // map client ids to server ids&lt;br /&gt;      IList&amp;lt;int&amp;gt; clientIds = new List&amp;lt;int&amp;gt;(idLookup.Keys);&lt;br /&gt;      foreach (var clientId in clientIds)&lt;br /&gt;         idCol.SetIdData(idLookup[clientId], lastId - --count);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The merge command class orchestrates all other classes and represents the consumer interface for this simple Bulk Data Persistence framework.&lt;br /&gt;&lt;br /&gt;The constructor gets the name of the database table, the name of the table-valued type and the data to be persisted.&lt;br /&gt;&lt;br /&gt;The properties &lt;i&gt;Connection&lt;/i&gt; and &lt;i&gt;Transaction&lt;/i&gt; are used to configure the destination database.&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;Columns:SqlMergeColumnCollection&amp;ltT&amp;gt;&lt;/i&gt; property enables the consumer to configure the mapping between a domain object and a database table.&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;Execute()&lt;/i&gt; method performs the database operation. It creates an ADO.NET &lt;i&gt;SqlCommand&lt;/i&gt;, specifies the dynamic T-SQL by calling the &lt;i&gt;GetCommandText():string&lt;/i&gt; method, executes the command and utilizes the &lt;i&gt;SyncSurrogateIds(SqlDataReader)&lt;/i&gt; method to synchronize the ids of added rows.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;As I wrote in my previous post, probably the SQL Server 2008 &lt;b&gt;MERGE&lt;/b&gt; statement performs better than classical separate &lt;b&gt;INSERT/UPDATE/DELETE&lt;/b&gt; operations. I have to investigate this and will share my results in a separate post.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How to use the Framework&lt;/h3&gt;Okay. Now we've got a shiny new framework. How to use?&lt;br /&gt;&lt;br /&gt;I recycle the test environment we've already seen in the previous post to persist &lt;i&gt;TestMany&lt;/i&gt; objects.&lt;br /&gt;&lt;br /&gt;Below a T-SQL DDL which specifies the destination table and the table-valued type DTO.&lt;br /&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;-- the database table&lt;br /&gt;CREATE TABLE TestMany (&lt;br /&gt;   Id int NOT NULL IDENTITY(1,1)&lt;br /&gt;      PRIMARY KEY CLUSTERED&lt;br /&gt;   ,SomeInt int NULL&lt;br /&gt;   ,SomeDate datetime NULL&lt;br /&gt;   ,SomeText varchar(100) NULL&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;-- the table-valued type DTO&lt;br /&gt;CREATE TYPE TestManyMergeType AS TABLE(&lt;br /&gt;   Id int NOT NULL&lt;br /&gt;   ,Action char(1) NOT NULL&lt;br /&gt;      CHECK (Action IN ('D', 'U', 'I'))&lt;br /&gt;   ,SomeInt int NULL&lt;br /&gt;   ,SomeDate datetime NULL&lt;br /&gt;   ,SomeText varchar(100) NULL&lt;br /&gt;   &lt;br /&gt;   ,PRIMARY KEY CLUSTERED &lt;br /&gt;      (Id, Action)&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;And our domain object which maps to the database table.&lt;br /&gt;&lt;pre class="brush: c-sharp;"&gt;&lt;br /&gt;public class TestMany&lt;br /&gt;{&lt;br /&gt;   public TestMany(int id, int someInt, DateTime someDate,&lt;br /&gt;                   string someText, ObjectState changeState) {&lt;br /&gt;      Id = id;&lt;br /&gt;      SomeInt = someInt;&lt;br /&gt;      SomeDate = someDate;&lt;br /&gt;      SomeText = someText;&lt;br /&gt;      ChangeState = changeState;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public int Id { get; set; }&lt;br /&gt;   public int SomeInt { get; set; }&lt;br /&gt;   public DateTime SomeDate { get; set; }&lt;br /&gt;   public string SomeText { get; set; }&lt;br /&gt;   public ObjectState ChangeState { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Anyway, what do we need to consume our framework?&lt;br /&gt;&lt;br /&gt;We need one class which inherits our &lt;i&gt;SqlMergeCommand&amp;lt;T&amp;gt;&lt;/i&gt; class to specify the column mapping.&lt;br /&gt;&lt;pre class="brush: c-sharp;"&gt;&lt;br /&gt;class TestManyMergeCommand : Sql2k8MergeCommand&amp;lt;TestMany&amp;gt;&lt;br /&gt;{&lt;br /&gt;   public TestManyMergeCommand(IEnumerable&amp;lt;TestMany&amp;gt; data)&lt;br /&gt;      : base("TestMany", "TestManyMergeType", &lt;br /&gt;             data.Where(t =&amp;gt; t.ChangeState != ObjectState.Unchanged)) {&lt;br /&gt;      // map the identity column&lt;br /&gt;      Columns.SetIdColumn("Id", (t) =&amp;gt; t.Id, (t, id) =&amp;gt; t.Id = id);&lt;br /&gt;      // map the merge action column&lt;br /&gt;      Columns.SetMergeColumn("Action", (t) =&amp;gt; t.ChangeState);&lt;br /&gt;      // map the data columns&lt;br /&gt;      Columns.AddDataColumn("SomeInt", SqlDbType.Int, &lt;br /&gt;                            (t) =&amp;gt; t.SomeInt);&lt;br /&gt;      Columns.AddDataColumn("SomeDate", SqlDbType.DateTime, &lt;br /&gt;                            (t) =&amp;gt; t.SomeDate);&lt;br /&gt;      Columns.AddDataColumn("SomeText", SqlDbType.VarChar, 100, &lt;br /&gt;                            (t) =&amp;gt; t.SomeText);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The class calls the base constructor to specify the destination table and the name of the table-valued type. The body of the constructor does the mapping. Done.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;(At this point I have to say "Thanks god for Lambda Expressions" to provide the callback methods. :-P )&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Last but not least a sample how to use this class to persist data.&lt;br /&gt;&lt;pre class="brush: c-sharp;"&gt;&lt;br /&gt;public void GenericMergeTest() {&lt;br /&gt;   using (SqlConnection cn = GetConnection(true))&lt;br /&gt;   using (SqlTransaction tran = cn.BeginTransaction()) {&lt;br /&gt;      // get test data&lt;br /&gt;      IList&amp;lt;TestMany&amp;gt; data = GetTestData(0);&lt;br /&gt;&lt;br /&gt;      TestManyMergeCommand mergeCommand = new TestManyMergeCommand(data);&lt;br /&gt;      mergeCommand.Connection = cn;&lt;br /&gt;      mergeCommand.Transaction = tran;&lt;br /&gt;      mergeCommand.Execute();&lt;br /&gt;&lt;br /&gt;      tran.Commit();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;As you see, we just have to initialize our custom command with data to be persisted, specify the database information and execute the command.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;As you see, the complete framework takes about 350 lines of code what sounds quiet fair to me.&lt;br /&gt;&lt;br /&gt;The merge command class can be plugged in to any existing O/R-Mapper framework which provides a "Unit of Work" functionality and a method/event to catch when data become persisted. If you like to use Bulk Data Persistence you don't have to rewrite your existing persistence layer.&lt;br /&gt;&lt;br /&gt;Note, I did not add any error handling to this sample. If you like to use this in your production environment you have to add this. (E.g. to avoid duplicate column names for the mapping.)&lt;br /&gt;&lt;br /&gt;If you already use an O/R-Mapper, you should change the way how to map your properties to columns. In this case you don't need a custom command for each of your domain objects, but you need a way to map the meta data of your O/R-Mapper to a merge command.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-7786956875591528085?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/7786956875591528085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2009/11/generic-bdp-approach-for-sql-server.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7786956875591528085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7786956875591528085'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2009/11/generic-bdp-approach-for-sql-server.html' title='A Generic BDP Approach for SQL Server 2008'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-3280245872952713856</id><published>2009-11-10T12:28:00.000-08:00</published><updated>2010-06-05T08:34:24.932-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>SQL Server and Bulk Data Persistence</title><content type='html'>In my last post I presented &lt;a href="http://florianreischl.blogspot.com/2009/11/bulk-data-persistence-pattern.html"&gt;Bulk Data Persistence (BDP)&lt;/a&gt; as a general concept to send bulks of data data from a client to a database server.&lt;br /&gt;&lt;br /&gt;Today I'll show you ways how to use BDP with SQL Server.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Sample Environment&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;To avoid duplicate source code I'll start with a short description of the environment we will work with.&lt;br /&gt;&lt;br /&gt;The database actually contains one table "TestMany" which is described by the following listing and contains about 1,000,000 rows. The following DDL statement describes the structure of the "TestMany" table.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: sql;"&gt;CREATE TABLE dbo.TestMany (&lt;br /&gt;   Id int IDENTITY(1,1) NOT NULL&lt;br /&gt;      PRIMARY KEY CLUSTERED&lt;br /&gt;   ,SomeInt int NULL&lt;br /&gt;   ,SomeDate datetime NULL&lt;br /&gt;   ,SomeText varchar(100) NULL,&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;We use a domain objects from type &lt;i&gt;TestMany&lt;/i&gt; which represents a 1:1 mapping to our database table with an additional property to represent the state of the object.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;public class TestMany&lt;br /&gt;{&lt;br /&gt;   public TestMany(int id, int someInt, DateTime someDate, &lt;br /&gt;                   string someText, char changeState) {&lt;br /&gt;      Id = id;&lt;br /&gt;      SomeInt = someInt;&lt;br /&gt;      SomeDate = someDate;&lt;br /&gt;      SomeText = someText;&lt;br /&gt;      ChangeState = changeState;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public int Id { get; set; }&lt;br /&gt;   public int SomeInt { get; set; }&lt;br /&gt;   public DateTime SomeDate { get; set; }&lt;br /&gt;   public string SomeText { get; set; }&lt;br /&gt;   public char ChangeState { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Most likely you noticed the type &lt;i&gt;char&lt;/i&gt; of the &lt;i&gt;ChangeState&lt;/i&gt; property. Usually the change state of an objects should be represented as &lt;i&gt;enum&lt;/i&gt;, I choose this just to keep the following samples simple. To maintain the value of &lt;i&gt;ChangeState&lt;/i&gt; I'll use the following pseudo enum.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;public static class ObjectState&lt;br /&gt;{&lt;br /&gt;   public const char Added = 'I';&lt;br /&gt;   public const char Deleted = 'D';&lt;br /&gt;   public const char Changed = 'U';&lt;br /&gt;   public const char Unchanged = 'X';&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Since we'll send a complete package of data to the database we have to tell it how to handle specific rows. Therefore I'll use the simple characters "I" (for INSERT), "U" (for UPDATE) and "D" (for DELETE). The &lt;i&gt;Unchanged&lt;/i&gt; is not really needed in our samples, but added for completeness.&lt;br /&gt;&lt;br /&gt;To avoid writing a connection string always and always again I use a simple helper method which gets a connection string from app.config and opens the connection automatically.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;private SqlConnection GetConnection(bool open) {&lt;br /&gt;   SqlConnection cn;&lt;br /&gt;   cn = new SqlConnection(Properties.Settings.Default.SandboxOnSql2k801);&lt;br /&gt;   if (open)&lt;br /&gt;      cn.Open();&lt;br /&gt;   return cn;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;To create &lt;i&gt;TestMany&lt;/i&gt; objects to be persisted we'll use the following &lt;i&gt;GetTestData()&lt;/i&gt; method.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;private IList&amp;lt;testmany&amp;gt; GetTestData() {&lt;br /&gt;   List&amp;lt;testmany&amp;gt; data = new List&amp;lt;testmany&amp;gt;();&lt;br /&gt;&lt;br /&gt;   // to update&lt;br /&gt;   for (int i = 1; i &amp;lt;= 1000; i++)&lt;br /&gt;      data.Add(new TestMany(&lt;br /&gt;         i, &lt;br /&gt;         i, &lt;br /&gt;         DateTime.Now.AddSeconds(i),&lt;br /&gt;         string.Format("Updated {0}", i),&lt;br /&gt;         ObjectState.Changed));&lt;br /&gt;&lt;br /&gt;   // to delete&lt;br /&gt;   for (int i = 20000; i &amp;lt;= 21000; i++)&lt;br /&gt;      data.Add(new TestMany(&lt;br /&gt;         i, &lt;br /&gt;         0, &lt;br /&gt;         DateTime.Now,&lt;br /&gt;         null,&lt;br /&gt;         ObjectState.Deleted));&lt;br /&gt;&lt;br /&gt;   // to insert&lt;br /&gt;   for (int i = -1; i &amp;gt;= -1000; i--)&lt;br /&gt;      data.Add(new TestMany(&lt;br /&gt;         i, &lt;br /&gt;         i, &lt;br /&gt;         DateTime.Now.AddSeconds(i),&lt;br /&gt;         string.Format("Added {0}", i),&lt;br /&gt;         ObjectState.Added));&lt;br /&gt;&lt;br /&gt;   return data;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Important:&lt;/b&gt; To get BDP work we need a unique surrogate id for new objects which will be send to the database and mapped to the new generated Ids in the client. I work with  negative integer numbers in the previous method.&lt;br /&gt;&lt;br /&gt;Since we will persist a complete bulk of objects in one database round trip we need a slightly different way to get the server side generated IDENTITY values for new inserted objects. When persisting single objects we can use the SCOPE_IDENTITY() (or @@IDENTITY) function to get the id of the last inserted row. With BDP we send all new rows in one operation, so we have to synchronize all new ids after this operation. The following method gets all data which have been handled in a BDP operation, the count of inserted rows (returned by the database) and the id of the last inserted row (returned by the database). Later in this post, we'll see how we get those information and how to keep them valid. For the moment I just want to show you how to synchronize the client ids with the specified last id and the count of added objects. Probably it makes sense to jump over this method for the moment and come back when we did the first BDP operations.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;private void SyncAddedIds(IEnumerable&amp;lt;TestMany&amp;gt; data, int count, int lastId) {&lt;br /&gt;&lt;br /&gt;   // get surrogate client ids for new added items&lt;br /&gt;   SortedList&amp;lt;int, TestMany&amp;gt; idLookup = new SortedList&amp;lt;int, TestMany&amp;gt;(count);&lt;br /&gt;   foreach (var item in data)&lt;br /&gt;      if (item.ChangeState == ObjectState.Added)&lt;br /&gt;         idLookup.Add(item.Id, item);&lt;br /&gt;&lt;br /&gt;   // map client ids to server ids&lt;br /&gt;   IList&amp;lt;int&amp;gt; clientIds = new List&amp;lt;int&amp;gt;(idLookup.Keys);&lt;br /&gt;   foreach (var clientId in clientIds)&lt;br /&gt;      idLookup[clientId].Id = lastId - --count;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;SQL Server 2008 Configuration&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;To use BDP in SQL Server 2008, we need to define table-valued types for the data to be persisted in bulk. We will use these types as simple &lt;a href="http://en.wikipedia.org/wiki/Data_Transfer_Object"&gt;Data Transfer Objects (DTOs)&lt;/a&gt; to transfer structural data from the client to the database.&lt;br /&gt;&lt;br /&gt;Notice: We are &lt;b&gt;not&lt;/b&gt; needed to use stored procedures for BDP. We will see a sample using a SP but we will also see another sample which work without any procedure.&lt;br /&gt;&lt;br /&gt;The table-valued type DTO for our &lt;i&gt;TestMany&lt;/i&gt; class and table looks just like our class, containing a column &lt;i&gt;Action&lt;/i&gt; which represents the kind of operation to be executed with each row.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;CREATE TYPE TestManyMergeType AS TABLE (&lt;br /&gt;   Id int NOT NULL&lt;br /&gt;   ,Action char(1) NOT NULL&lt;br /&gt;      CHECK (Action IN ('D', 'U', 'I'))&lt;br /&gt;   ,SomeInt int NULL&lt;br /&gt;   ,SomeDate datetime NULL&lt;br /&gt;   ,SomeText varchar(100) NULL&lt;br /&gt;   ,PRIMARY KEY CLUSTERED (Id, Action)&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;The PRIMARY KEY on the Id and Action columns is important to ensure integrity and optimizes the lookup performance when we merge data. I also defined a CHECK constraint for the "Action" column for my personal paranoia :-) - to avoid wrong data.&lt;br /&gt;&lt;br /&gt;As a little hint: Keep all lookup columns (Id and Action in this case) at the beginning of the table. Try to avoid them at the end, especially after any columns with variable length (as SomeText). This could be another paranoia statement in case of our DTO, but is important with real tables.&lt;br /&gt;&lt;br /&gt;With this type our database is ready to handle BDP operations. Let's start with some samples.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;SQL Server 2008 and Stored Procedures&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;We start with the stored procedure sample because it separates the two parts of the party and makes it easier to discuss each of them separately.&lt;br /&gt;&lt;br /&gt;Let's start with the stored procedure definition.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: sql;"&gt;ALTER PROCEDURE MergeTestMany&lt;br /&gt;   @data TestManyMergeType READONLY&lt;br /&gt;AS&lt;br /&gt;   -- delete&lt;br /&gt;   DELETE trg &lt;br /&gt;      FROM TestMany trg &lt;br /&gt;      WHERE EXISTS (&lt;br /&gt;         SELECT * &lt;br /&gt;         FROM @data src &lt;br /&gt;         WHERE src.Id = trg.Id AND src.Action = 'D'&lt;br /&gt;         );&lt;br /&gt;&lt;br /&gt;   -- update&lt;br /&gt;   UPDATE trg SET &lt;br /&gt;         SomeInt = src.SomeInt&lt;br /&gt;         ,SomeDate = src.SomeDate&lt;br /&gt;         ,SomeText = src.SomeText&lt;br /&gt;      FROM TestMany trg &lt;br /&gt;         JOIN @data src &lt;br /&gt;         ON trg.Id = src.Id AND src.Action = 'U';&lt;br /&gt;&lt;br /&gt;   -- insert&lt;br /&gt;   INSERT INTO TestMany&lt;br /&gt;      SELECT SomeInt,SomeDate,SomeText &lt;br /&gt;      FROM @data &lt;br /&gt;      WHERE Action = 'I' &lt;br /&gt;      ORDER BY Id -- ## IMPORTANT to match ids in client&lt;br /&gt;&lt;br /&gt;   -- return last IDENTITY and count of added rows&lt;br /&gt;   SELECT SCOPE_IDENTITY(), @@ROWCOUNT;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;The procedure gets one table-valued parameter with the melodic name @data (feel free to change this to a more specific name). Table-valued parameters are a new and very powerful feature of SQL Server 2008 to send a complete set of data to the server. The procedure body represents four separate parts.&lt;br /&gt;&lt;br /&gt;As first we use a &lt;i&gt;DELETE&lt;/i&gt; statement to delete all provided data which are marked with a "D"-action and matched by a specified Id. (At this point I have to say thank's to Paul White - a real SQL guru - from &lt;a href="http:///www.sqlservercentral.com"&gt;SQLServerCentral.com&lt;/a&gt; for his explanation of the left semi join when using &lt;i&gt;EXISTS&lt;/i&gt; &lt;a href="http://www.sqlservercentral.com/Forums/Topic815335-338-1.aspx"&gt;here&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;The second part of the procedure uses a joined &lt;i&gt;UPDATE&lt;/i&gt; to update all existing data with their new values which are marked a "U"-action.&lt;br /&gt;&lt;br /&gt;The third part simply inserts all provided DTOs which are marked with "I". Spot the &lt;i&gt;ORDER BY&lt;/i&gt; for the source data. This ordering is very important to ensure the rows to be inserted in the order of the specified surrogate ids from client to be able to calculate the generated server IDENTITY values in the client application.&lt;br /&gt;&lt;br /&gt;Last but not least we return the last generated IDENTITY value and the count of rows which have been newly inserted into our table. Feel free to scroll up at to the &lt;i&gt;SyncAddedIds&lt;/i&gt; method which should be more comprehensible now since this is the most tricky and most important part to get a well working bulk insert operation.&lt;br /&gt;&lt;br /&gt;Let's move to the client side implementation.&lt;br /&gt;&lt;br /&gt;To provide a table-valued parameter from ADO.NET to SQL Server 2008, there are two different ways. You can provide a &lt;i&gt;DataTable&lt;/i&gt; or an implementation of an &lt;i&gt;IEnumerable&amp;lt;Microsoft.SqlServer.Server.SqlDataRecord&amp;gt;&lt;/i&gt; which returns all data to be transfered to the parameter. Personally I prefer the enumerator since a &lt;i&gt;DataTable&lt;/i&gt; always represents a not needed overhead and requires relatively much memory.&lt;br /&gt;&lt;br /&gt;The following listing shows a quiet straight forward implementation of this enumerable for our &lt;i&gt;TestMany&lt;/i&gt; domain object.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;class TestManyEnumerator : IEnumerable&amp;lt;SqlDataRecord&amp;gt;&lt;br /&gt;{&lt;br /&gt;   public TestManyEnumerator(IEnumerable&amp;lt;TestMany&amp;gt; data) {&lt;br /&gt;      _data = data;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private IEnumerable&amp;lt;TestMany&amp;gt; _data;&lt;br /&gt;&lt;br /&gt;   public IEnumerator&amp;lt;SqlDataRecord&amp;gt; GetEnumerator() {&lt;br /&gt;      SqlMetaData[] metaData = {&lt;br /&gt;         new SqlMetaData("Id", SqlDbType.Int),&lt;br /&gt;         new SqlMetaData("MergeAction", SqlDbType.Char, 1),&lt;br /&gt;         new SqlMetaData("SomeInt", SqlDbType.Int),&lt;br /&gt;         new SqlMetaData("SomeDate", SqlDbType.DateTime),&lt;br /&gt;         new SqlMetaData("SomeText", SqlDbType.VarChar, 100),&lt;br /&gt;      };&lt;br /&gt;&lt;br /&gt;      foreach (var item in _data) {&lt;br /&gt;         SqlDataRecord record = new SqlDataRecord(metaData);&lt;br /&gt;&lt;br /&gt;         record.SetValue(0, item.Id);&lt;br /&gt;         record.SetValue(1, item.ChangeState);&lt;br /&gt;         record.SetValue(2, item.SomeInt);&lt;br /&gt;         record.SetValue(3, item.SomeDate);&lt;br /&gt;         record.SetValue(4, item.SomeText);&lt;br /&gt;&lt;br /&gt;         yield return record;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {&lt;br /&gt;      return this.GetEnumerator();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;As you see, the &lt;i&gt;GetEnumerator()&lt;/i&gt; first creates an array of &lt;i&gt;SqlMetaData&lt;/i&gt; which is required for the constructor of a &lt;i&gt;SqlDataRecord&lt;/i&gt; objects. After this we have to set the values of the current &lt;i&gt;TestMany&lt;/i&gt; object and return it.&lt;br /&gt;&lt;br /&gt;The next sample shows how to call our stored procedure from ADO.NET.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;using (SqlConnection cn = GetConnection(true))&lt;br /&gt;using (SqlTransaction tran = cn.BeginTransaction()) {&lt;br /&gt;   // get test data&lt;br /&gt;   IList&amp;lt;TestMany&amp;gt; data = GetTestData();&lt;br /&gt;&lt;br /&gt;   // create a new command as stored procedure&lt;br /&gt;   SqlCommand cmd = new SqlCommand("MergeTestMany", cn);&lt;br /&gt;   cmd.CommandType = CommandType.StoredProcedure;&lt;br /&gt;   cmd.Transaction = tran;&lt;br /&gt;   // create a new parameter ("Structured" defines a TVP)&lt;br /&gt;   SqlParameter p = cmd.Parameters.Add("@data", SqlDbType.Structured);&lt;br /&gt;   // specify the name of the TVP&lt;br /&gt;   p.TypeName = "TestManyMergeType";&lt;br /&gt;   p.Value = new TestManyEnumerator(data);&lt;br /&gt;&lt;br /&gt;   // catch the returned IDENTITY information&lt;br /&gt;   using (SqlDataReader reader = cmd.ExecuteReader()) {&lt;br /&gt;      reader.Read();&lt;br /&gt;      int lastId = reader.IsDBNull(0) ? -1 : (int)reader.GetDecimal(0);&lt;br /&gt;      int count = reader.GetInt32(1);&lt;br /&gt;      // synchronize all newly added keys&lt;br /&gt;      SyncAddedIds(data, count, lastId);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   tran.Commit();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;As you see, to call a procedure which receives a table-valued parameter we have to specify a &lt;i&gt;SqlParameter&lt;/i&gt; as &lt;i&gt;SqlDbType.Structured&lt;/i&gt;, the name of the our T-SQL table-valued type as &lt;i&gt;TypeName&lt;/i&gt; and provide the above shown enumerator as value of the parameter. This enables ADO.NET to use a &lt;b&gt;single&lt;/b&gt; RPC call to utilize the procedure with &lt;b&gt;all&lt;/b&gt; changes which have been made on our objects.&lt;br /&gt;&lt;br /&gt;A &lt;i&gt;SqlDataReader&lt;/i&gt; gets the IDENTITY information, returned by the procedure, and calls the &lt;i&gt;SyncAddedIds&lt;/i&gt; method to set the newly generated ids to all our added domain objects.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Sadly, the current version of JDBC apparently not yet supports table-valued parameters. However, since there are many voices in the web (and on the &lt;a href="http://blogs.msdn.com/jdbcteam/default.aspx"&gt;Microsoft JDBC Driver Team Blog&lt;/a&gt;) I really hope this great feature will be added to the next version.&lt;/i&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;SQL Server 2008 without Procedures&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;Sure, if we don't work with stored procedures (probably we use an O/R-Mapper) in our environment, we are still able to realize BDP.&lt;br /&gt;&lt;br /&gt;Whenever we changed domain objects in memory for a specific business case there will come the point where we have to persist the data to the database. At this position we usually generate some dynamic SQL statements to send the changes to the database. This is the position where we just have to replace the existing single-row CRUD statements with bulk operation statements as we've already seen in the procedural approach. ADO.NET is able to bind table-valued parameters to any custom SQL command.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Important: &lt;/b&gt;As in the procedural approach, we need a table-valued type which can be used as DTO when communicating with the database and an implementation of a &lt;i&gt;IEnumerable&amp;lt;SqlDataRecord&amp;gt;&lt;/i&gt; (or a &lt;i&gt;DataTable&lt;/i&gt; which can be provided as value for the &lt;i&gt;SqlParameter&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;When we compare the following snippet with the stored procedure solution we'll see, the only difference is the custom SQL instead of a stored procedure call.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;using (SqlConnection cn = GetConnection(true))&lt;br /&gt;using (SqlTransaction tran = cn.BeginTransaction()) {&lt;br /&gt;   // get test data&lt;br /&gt;   IList&amp;lt;TestMany&amp;gt; data = GetTestData();&lt;br /&gt;&lt;br /&gt;   // create the complete DELETE/UPDATE/INSERT sql command&lt;br /&gt;   String sql = @"&lt;br /&gt;      DELETE trg FROM TestMany trg WHERE EXISTS(&lt;br /&gt;         SELECT * FROM @data src WHERE src.Id = trg.Id AND src.Action = 'D'&lt;br /&gt;         );&lt;br /&gt;&lt;br /&gt;      UPDATE trg SET SomeInt=src.SomeInt, &lt;br /&gt;                     SomeDate=src.SomeDate, &lt;br /&gt;                     SomeText=src.SomeText&lt;br /&gt;         FROM TestMany trg &lt;br /&gt;         JOIN @data src ON trg.Id = src.Id AND src.Action='U';&lt;br /&gt;&lt;br /&gt;      INSERT INTO TestMany&lt;br /&gt;         SELECT SomeInt,SomeDate,SomeText &lt;br /&gt;         FROM @data &lt;br /&gt;         WHERE Action='I' &lt;br /&gt;         ORDER BY Id -- &amp;lt;- IMPORTANT to match ids in client&lt;br /&gt;&lt;br /&gt;      SELECT SCOPE_IDENTITY(), @@ROWCOUNT;&lt;br /&gt;      ";&lt;br /&gt;&lt;br /&gt;   SqlCommand cmd = new SqlCommand(sql, cn);&lt;br /&gt;   cmd.Transaction = tran;&lt;br /&gt;   // create a new table-valued parameter for our TestManyMergeType type&lt;br /&gt;   SqlParameter p = cmd.Parameters.Add("@data", SqlDbType.Structured);&lt;br /&gt;   p.TypeName = "TestManyMergeType";&lt;br /&gt;   // provide the data&lt;br /&gt;   p.Value = new TestManyEnumerator(data);&lt;br /&gt;&lt;br /&gt;   // execute the sql command and map the returned server ids&lt;br /&gt;   using (SqlDataReader reader = cmd.ExecuteReader()) {&lt;br /&gt;      reader.Read();&lt;br /&gt;      int lastId = reader.IsDBNull(0) ? -1 : (int)reader.GetDecimal(0);&lt;br /&gt;      int count = reader.GetInt32(1);&lt;br /&gt;      SyncAddedIds(data, count, lastId);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   tran.Commit();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Indeed, usually we will never put such dynamic SQL statements to our client application. Those statements will be generated by a generic implementation within an O/R-Mapper or any other data access layer.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;BDP and SQL Server 2005&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;Sadly, table-valued types have just been introduced with SQL Server 2008, what means they are not available in SQL Server 2005 and previous version. The DTOs could be realized with user defined CLR types but SQL Server does not support arrays like other database systems. Therefore BDP is not possible to use with SQL Server 2005.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;One workaround might be to create a XML document which contains the data to be persisted but this is a hard way to go and requires deep performance tests. I successfully used this for larger operations (more than 10,000 rows in one batch) but I have no experiences with general solutions for client layers.&lt;/i&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;We have seen how we can realize Bulk Data Persistence when using SQL Server 2008. We need a table-valued type defined in SQL Server which can be used as Data Transer Object and an enumerator for &lt;i&gt;SqlDataRecord&lt;/i&gt; objects.&lt;br /&gt;&lt;br /&gt;Hence, if you do not want to use user-defined table-valued types in your database BDP is not the right way to go in your system.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;Outstanding&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;Probably the idea of BDP sounds nice for you. Nevertheless, one important part is missing here. A comparison with a single statement based solution. I'll provide this in a following post and reference it here.&lt;br /&gt;&lt;i&gt;Edit: &lt;a href="http://florianreischl.blogspot.com/2009/11/table-valued-parametes-performance.html"&gt;Table-Valued Parameters - A Performance Comparison&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Since it would be way too much source to code for lazy people like me, I'll also provide a possible implementation of a generic approach which can be used for any kind of domain object.&lt;br /&gt;&lt;i&gt;Edit: &lt;a href="http://florianreischl.blogspot.com/2009/11/generic-bdp-approach-for-sql-server.html"&gt;A Generic BDP Approach for SQL Server 2008&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;For the database gurus out there I'll provide an special post where I'll compare the classical INSERT/DELETE/UPDATE functions to the shiny new &lt;b&gt;MERGE&lt;/b&gt; function which was introduced with SQL Server 2008. Since now my tests are not stressful enough to provide a real statement about.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-3280245872952713856?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/3280245872952713856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2009/11/sql-server-and-bulk-data-persistence.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/3280245872952713856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/3280245872952713856'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2009/11/sql-server-and-bulk-data-persistence.html' title='SQL Server and Bulk Data Persistence'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-285864697587326937</id><published>2009-11-07T12:14:00.000-08:00</published><updated>2010-06-05T08:37:50.421-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Bulk Data Persistence Pattern</title><content type='html'>"Bulk Data Persistence" (BDP) covers a problem I've seen many times in while doing my business or speaking with people all over the world. BDP is an extension of the &lt;a href="http://martinfowler.com/eaaCatalog/unitOfWork.html"&gt;"Unit of Work" (UoW)&lt;/a&gt; pattern, defined by by &lt;a href="http://www.martinfowler.com/"&gt;Martin Fowler&lt;/a&gt; in his great book &lt;a href="http://www.martinfowler.com/books.html#eaa"&gt;Patterns of Enterprise Application Architecture (PoEAA)&lt;/a&gt;. BDP describes a different way how clients communicate with their persistence layer to save changes.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;A Real-Life Scenario&lt;/h3&gt;Guess it's Sunday morning. You stand up, go to bath for oral hygiene and taking a shower. After that you dress up.&lt;br /&gt;&lt;br /&gt;Now you leave your house/flat, go to the baker and buy &lt;b&gt;one&lt;/b&gt; biscuit (a bab if you live in England or a Semmel if you live in Bavaria - like I do :-D ); back at home you put your biscuit (bab/Semmel) onto the kitchen table. Now you leave your house again, go to the baker to buy the biscuit (bab/Semmel) for your husband or wife; back to home and put it onto the kitchen table. Since you have two children and mom is currently visiting you end up with five trips to the baker and back.&lt;br /&gt;&lt;br /&gt;Sure, you'd never do this. You go to the backer and take all biscuits (babs/Semmeln) for the whole family in one round trip. However this is a good example to see how software interacts with databases.&lt;br /&gt;&lt;h3&gt;A Technical Scenario&lt;/h3&gt;Guess a system is made to enter orders.&lt;br /&gt;&lt;br /&gt;The user creates a new order and adds ten order positions. The implementation of this might be realized with a UoW design. When hitting the save button the business logic layer (BLL) validates the order and all oder positions against existing business rules. When everything is fine the client opens a connection to the persistence tier (usually a database). The data access layer (DAL) maps the order object to a "Orders" table and sends row to the database. When the order was inserted the DAL maps the first order position object to the OrderPositions table and sends a row to the database. When this operation returns it maps the next oder position and sends the next row to the database. And so on...&lt;br /&gt;&lt;br /&gt;Hence, quiet same scenario as the real-live baker sample.&lt;br /&gt;&lt;h3&gt;Tip to the Balance&lt;/h3&gt;Todays systems become larger and larger and the count of data to be persisted heavily grows, too. Scalability is a very important design for applications like web applications or service endpoints. A scalable designed application enables the production provider to use load balancing technologies to host the applications on several boxes.&lt;br /&gt;&lt;br /&gt;Unfortunately, the operational persistence layer is almost never scalable. It is possible to use replication or data-warehouse architectures to move reporting processes away form the operational system. Nevertheless, business C(R)UD operations always have to work on the one and only operational database and this database is a common bottleneck of several system.&lt;br /&gt;&lt;h3&gt;A short look into the Unit of Work (UoW)&lt;/h3&gt;Since Bulk Data Persistence (BDP) pattern is a extension of the Unit of Work (UoW) pattern I'll start with a short description of UoW pattern. &lt;br /&gt;&lt;br /&gt;The UoW describes a client side transaction object which registers all object changes during one complete business operation. In our sample of the order system, an order only makes sense with all of it's order positions. The UoW transaction object holds the order and all order positions until everything becomes stored in the database.&lt;br /&gt;&lt;br /&gt;The following diagram shows the most important part of the UoW pattern needed to understand BDP.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_hBTxNhEL4oY/Svm8V5bTm4I/AAAAAAAAAB4/zJq0Bt9R3BY/s1600-h/Unit+of+Work.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_hBTxNhEL4oY/Svm8V5bTm4I/AAAAAAAAAB4/zJq0Bt9R3BY/s400/Unit+of+Work.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;I abstracted the data persistence part since this is the important we will look at in the following text.&lt;br /&gt;&lt;br /&gt;A classic implementation of the data persistence would be single database operations for each object which was changed within the UoW. The following diagram describes this approach.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_hBTxNhEL4oY/Svm8lO9JQpI/AAAAAAAAACA/PteAsvul6EQ/s1600-h/Single+Data+Persistence.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_hBTxNhEL4oY/Svm8lO9JQpI/AAAAAAAAACA/PteAsvul6EQ/s400/Single+Data+Persistence.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;In our sample order system we would generate 11 single database operations. One to insert a row into the Orders table and ten to insert the rows into the OrderPositions table.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Bulk Data Persistence Pattern&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;Bulk Data Persistence means to aggregate all data operations of one object type and send them as one &amp;nbsp;single database operation to the database system.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_hBTxNhEL4oY/Svm8q8TJeuI/AAAAAAAAACI/GDtsUVQpYyo/s1600-h/Bulk+Data+Persistence.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_hBTxNhEL4oY/Svm8q8TJeuI/AAAAAAAAACI/GDtsUVQpYyo/s400/Bulk+Data+Persistence.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The idea of BDP is to enable the database system to do what it is really optimized for, work with bulks of data. This usually causes way faster statement execution and even better responsibility for concurrent applications since one larger lock works faster than many small locks caused by many single persistence operations. Last but not least the network round trips of the clients are reduced to a minimum what also causes a faster execution.&lt;br /&gt;&lt;br /&gt;In our order system sample there would be just two database operations. One to insert the new Order row and one to insert all the OrderPosition rows.&lt;br /&gt;&lt;br /&gt;In this sample 11 single statements seem to be no problem but consider the number of concurrent users.&lt;br /&gt;&lt;br /&gt;Another scenario can be a process which synchronizes data between a distributed database system or a process which imports data from another system. Both these scenarios might work with thousands of rows to be saved.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What BDP does not cover&lt;/h3&gt;Please Don't misunderstand. The idea of BDP is &lt;b&gt;not&lt;/b&gt; to move business logic into the database! Don't try to move &lt;b&gt;all&lt;/b&gt; changed object types of one UoW in one package to the database. When your database handles complete messages of business objects, it becomes a data service and that's usually not the intention in todays software development. Instead of this send one data package &lt;b&gt;per type&lt;/b&gt;. BDP covers the same functionality and contract as any single data persisting data access layer and persistence tier.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Outstanding&lt;/h3&gt;I'll provide some different samples in the next days to show how it works and what's the profit. Links to these samples will be added here.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://florianreischl.blogspot.com/2009/11/sql-server-and-bulk-data-persistence.html"&gt;SQL Server and Bulk Data Persistence&lt;/a&gt;&lt;/li&gt;&lt;li&gt;PostgreSQL and Bulk Data Persistence - pending&lt;/li&gt;&lt;li&gt;Oracle and Bulk Data Persistence - pending&lt;/li&gt;&lt;li&gt;&lt;a href="http://florianreischl.blogspot.com/2009/11/generic-bdp-approach-for-sql-server.html"&gt;A Generic BDP Approach for SQL Server 2008&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://florianreischl.blogspot.com/2009/11/table-valued-parametes-performance.html"&gt;SQL Server Table-Valued Parameters - A Performance Comparison&lt;/a&gt;&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/6936017315111598402-285864697587326937?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/285864697587326937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2009/11/bulk-data-persistence-pattern.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/285864697587326937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/285864697587326937'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2009/11/bulk-data-persistence-pattern.html' title='Bulk Data Persistence Pattern'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_hBTxNhEL4oY/Svm8V5bTm4I/AAAAAAAAAB4/zJq0Bt9R3BY/s72-c/Unit+of+Work.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-980055971615518811</id><published>2009-10-10T11:27:00.000-07:00</published><updated>2009-11-21T07:46:39.398-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><title type='text'>Factory Pattern</title><content type='html'>&lt;div style="text-align: justify;"&gt;The factory pattern is probably of the most common creational pattern.&lt;br /&gt;&lt;br /&gt;What is a "creational" pattern?&lt;br /&gt;&lt;br /&gt;A creational pattern is pattern which describes ways to create objects. You can call it an abstraction of the &lt;i&gt;new&lt;/i&gt; operator. The gain of factory classes is to encapsulate the creation of objects to a central position - the factory - and ensure that an object becomes correct initialized. A well known factory is the static &lt;i&gt;XmlWriter.Create()&lt;/i&gt; method. It gets either a file name or an output stream and an optional &lt;i&gt;XmlWriterSettings&lt;/i&gt; parameter which specifies things like formatting behavior of the returned &lt;i&gt;XmlWriter&lt;/i&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Sample Scenario&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Before we start to show how the factory works I'll define a sample scenario. Our system is a ordering system which handles "Order" and "Customer" objects and we got the following classes.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;public class Order : ICreationInformation&lt;br /&gt;{&lt;br /&gt;   public DateTime CreationDate { get; set; }&lt;br /&gt;   public String CreationUser { get; set; }&lt;br /&gt;   public String OrderNo { get; set; }&lt;br /&gt;   public Decimal Amount { get; set; }&lt;br /&gt;   public Customer Customer { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Customer : ICreationInformation&lt;br /&gt;{&lt;br /&gt;   public DateTime CreationDate { get; set; }&lt;br /&gt;   public String CreationUser { get; set; }&lt;br /&gt;   public String Name { get; set; }&lt;br /&gt;&lt;br /&gt;   public override string ToString()&lt;br /&gt;   {&lt;br /&gt;      return this.Name;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;As you can see the "Order" as well as the "Customer" contain the system fields "CreationDate" and "CreationUser". In addition the order only becomes valid if it has a related "Customer".&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Problem of using the "new" operator&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Our ordering system might have more than one position where orders become created. If you work with &lt;i&gt;new&lt;/i&gt; operators to create a new "Order" wherever it is possible to create a new order you always have to specify the "CreationDate" and the "CreationUser". As first you might forget to set this information at one point. Remember Murphys law "Anything that can go wrong will go wrong.". As second you duplicate your source code. If you start with a "CreationDate" from local system it might be a future requirement to change this to use a server date since many computers don't have a correct configured local time. In this case you have to fly all over your code to find all position where you worked with local system time to set a "CreationDate".&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Factory&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;A factory class is a class which encapsulates the creation and correct initialization of objects.&lt;br /&gt;&lt;br /&gt;The following listing shows a sample factory to create "Customer" and "Order" objects.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;public class Factory&lt;br /&gt;{&lt;br /&gt;   public Customer CreateCustomer()&lt;br /&gt;   {&lt;br /&gt;      Customer customer = new Customer();&lt;br /&gt;&lt;br /&gt;      customer.CreationDate = DateTime.Now;&lt;br /&gt;      customer.CreationUser =&lt;br /&gt;         System.Security.Principal.WindowsIdentity.GetCurrent().Name;&lt;br /&gt;&lt;br /&gt;      return customer;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public Order CreateOrder()&lt;br /&gt;   {&lt;br /&gt;      Order order = new Order();&lt;br /&gt;&lt;br /&gt;      order.CreationDate = DateTime.Now;&lt;br /&gt;      order.CreationUser =&lt;br /&gt;         System.Security.Principal.WindowsIdentity.GetCurrent().Name;&lt;br /&gt;&lt;br /&gt;      return order;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Once created we can use our factory wherever we need a new "Order" or "Customer" object.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;Factory factory = new Factory();&lt;br /&gt;&lt;br /&gt;Customer customer = factory.CreateCustomer();&lt;br /&gt;customer.Name = "ALFKI";&lt;br /&gt;&lt;br /&gt;Order order = factory.CreateOrder();&lt;br /&gt;order.Customer = customer;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;To ensure that your objects are not created by using their constructor from outside the factory it makes sense to define an &lt;i&gt;internal&lt;/i&gt; constructor - if your objects are stored in a separate assembly. Now it is impossible to create one of these business objects without a correct initialization.&lt;br /&gt;&lt;br /&gt;In our simple example one factory fits to create both types of objects. In a real world scenario it might make sense to use specific factory classes for each type of a business object.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Abstract Factory&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;An abstract factory is a factory which can create different types of objects with a single implementation. In .NET a abstract factory can be realized with a generic method (or class).&lt;br /&gt;&lt;br /&gt;Maybe you noticed the &lt;i&gt;ICreationInformation&lt;/i&gt; interface which was added to our "Order" and "Customer" classes. Here is the definition of our this interface which provides the properties "CreationDate" and "CreationUser".&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;interface ICreationInformation&lt;br /&gt;{&lt;br /&gt;   DateTime CreationDate { get; set; }&lt;br /&gt;   String CreationUser { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;In addition we don't specify any constructor, so both objects have an &lt;b&gt;implicit public constructor&lt;/b&gt;. This enables us to create a generic function which can handles the creation of both objects with one implementation.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;public class AbstractFactory&lt;br /&gt;{&lt;br /&gt;   public T Create&amp;lt;T&amp;gt;()&lt;br /&gt;      where T : ICreationInformation, new()&lt;br /&gt;   {&lt;br /&gt;      T instance = new T();&lt;br /&gt;&lt;br /&gt;      instance.CreationDate = DateTime.Now;&lt;br /&gt;      instance.CreationUser =&lt;br /&gt;         System.Security.Principal.WindowsIdentity.GetCurrent().Name;&lt;br /&gt;&lt;br /&gt;      return instance;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;As you see, the method "Create" works with a generic type "T" with two constraints. The specified type has to be an implementation of &lt;i&gt;ICreationInformation&lt;/i&gt; and it needs an empty public constructor. If your business objects don't support an empty constructor you can use the not generic static method &lt;i&gt;System.Activator.Create()&lt;/i&gt; which creates objects and enables you to specify constructor arguments.&lt;br /&gt;&lt;br /&gt;The usage of this factory is quiet equal to the usual factory, you just have only one method and have to define the generic type.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;AbstractFactory factory = new AbstractFactory();&lt;br /&gt;&lt;br /&gt;Customer customer = factory.Create&amp;lt;Customer&amp;gt;();&lt;br /&gt;customer.Name = "ALFKI";&lt;br /&gt;&lt;br /&gt;Order order = factory.Create&amp;lt;Order&amp;gt;();&lt;br /&gt;order.Customer = customer;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Now that's cool. First, because we have just one implementation for probably hundreds of different objects which implement our &lt;i&gt;ICreationInformation&lt;/i&gt; interface and provide an empty public constructor. Second, if you a little bit like me, you are still feeling like a kid sometimes and have to say these generic approaches are always cool! :-)&lt;br /&gt;&lt;br /&gt;I'm afraid to say, these abstract factories are not as cool as they look at the first moment. The generic approach is a huge restriction for a factory. Suggest you would be more restrictive as we have been since now. Eventually you wouldn't like to enable the user of your factory to create any "Order" without specifying a "Customer". In a usual factory you just change the "CreateOrder" function to get an instance of a "Customer" object. An abstract factory cannot handle special business cases like this.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Combine Both&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;As we saw an abstract factory seems to be nice to do some general initializations for objects, but it's a week solution for specific requirements. Anyway, it helps to avoid duplicated code. So why not combining both? You should use a non abstract factory to create new business objects within an application which consumes your business layer but you can use the abstract factory within other factories.&lt;br /&gt;&lt;br /&gt;Here is a new version of our factory classes.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;class AbstractFactory&lt;br /&gt;{&lt;br /&gt;   internal T Create&amp;lt;T&amp;gt;()&lt;br /&gt;      where T : ICreationInformation, new()&lt;br /&gt;   {&lt;br /&gt;      T instance = new T();&lt;br /&gt;&lt;br /&gt;      instance.CreationDate = DateTime.Now;&lt;br /&gt;      instance.CreationUser =&lt;br /&gt;         System.Security.Principal.WindowsIdentity.GetCurrent().Name;&lt;br /&gt;&lt;br /&gt;      return instance;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Factory&lt;br /&gt;{&lt;br /&gt;   AbstractFactory _abstract = new AbstractFactory();&lt;br /&gt;&lt;br /&gt;   public Customer CreateCustomer()&lt;br /&gt;   {&lt;br /&gt;      Customer customer = _abstract.Create&amp;lt;Customer&amp;gt;();&lt;br /&gt;      return customer;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public Order CreateOrder(Customer customer)&lt;br /&gt;   {&lt;br /&gt;      if (customer == null)&lt;br /&gt;         throw new ArgumentNullException("customer");&lt;br /&gt;&lt;br /&gt;      Order order = _abstract.Create&amp;lt;Order&amp;gt;();&lt;br /&gt;      order.Customer = customer;&lt;br /&gt;&lt;br /&gt;      return order;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;As you see, the abstract factory became a private class. So it is not possible to use it from outside of our assembly. The usual factory has an instance of an abstract factory to use it's gain to avoid duplicate code for the &lt;i&gt;ICreationInformation&lt;/i&gt; interface members. The "CreateOrder" method became more restrictive to ensure that no order can be created without a specified instance of a "Customer".&lt;br /&gt;&lt;br /&gt;Now the consumer can use a secure and handy factory and everything is ensured to be done correct.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;Factory factory = new Factory();&lt;br /&gt;&lt;br /&gt;Customer customer = factory.CreateCustomer();&lt;br /&gt;customer.Name = "ALFKI";&lt;br /&gt;&lt;br /&gt;Order order = factory.CreateOrder(customer);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;As you saw, the factory pattern is a helpful way to ensure correct initialized objects. The abstract factory is more a tool to be used for less complex requirements but it can be very helpful to do basic initializations.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-980055971615518811?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/980055971615518811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2009/10/factory-pattern.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/980055971615518811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/980055971615518811'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2009/10/factory-pattern.html' title='Factory Pattern'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-7023951797495057434</id><published>2009-10-05T13:37:00.000-07:00</published><updated>2009-11-21T08:05:13.674-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><category scheme='http://www.blogger.com/atom/ns#' term='threading'/><title type='text'>Easy Working with Threads</title><content type='html'>&lt;div style="text-align: justify;"&gt;.NET 4.0 introduces the new Parallelism namespace which will simplify working with threads. So, as long as we are &lt;i&gt;just&lt;/i&gt; .NET 3.5 coders we have to wait and keep our hands of these complicated multi-threading, don't we? We don't! I'll show you some approaches how to work clean and simple in a multi-threaded environment.&lt;br /&gt;&lt;br /&gt;If you just need to start threads which have to do some work without returning any information back to the caller you are usually out of any problems. Start your threads and let them go.&lt;br /&gt;&lt;br /&gt;Unfortunately, most times this is not the way how to work with threads usually you have an application thread which dispatches a set of tasks but needs the result of those tasks to work with. We'll simulate this with a "Task" class which will be provided to the worker methods within the following samples.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Our Task Class&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In the following samples we will work with a "Task" class which will be provided to our threads to simulate a asynchronous work. Here is the definition of this class.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;// represents a task which shall be handled by &lt;br /&gt;// asynchronous working thread&lt;br /&gt;class Task&lt;br /&gt;{&lt;br /&gt;   public int Id { get; set; }&lt;br /&gt;   public int ReturnValue { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Classic Thread Approach&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Let's start with the old-school solution, which uses &lt;i&gt;lock&lt;/i&gt; to ensure thread safe working.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;// monitor the count of working threads&lt;br /&gt;static int _workingTasks;&lt;br /&gt;&lt;br /&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;   // count of tasks to be simulated&lt;br /&gt;   int taskCount = 10;&lt;br /&gt;   // hold the dispated tasks to work with the results&lt;br /&gt;   List&lt;task&gt; tasks = new List&lt;task&gt;();&lt;br /&gt;&lt;br /&gt;   // first set the complete count of working tasks&lt;br /&gt;   _workingTasks = taskCount;&lt;br /&gt;&lt;br /&gt;   for (int i = 0; i &lt; taskCount; i++)&lt;br /&gt;   {&lt;br /&gt;      // create a new thread&lt;br /&gt;      Thread thread = new Thread(new ParameterizedThreadStart(DoWork));&lt;br /&gt;&lt;br /&gt;      // create and remember the task&lt;br /&gt;      Task task = new Task { Id = i };&lt;br /&gt;      tasks.Add(task);&lt;br /&gt;      // start the thread&lt;br /&gt;      thread.Start(task);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   while (_workingTasks != 0)&lt;br /&gt;   {&lt;br /&gt;      // wait until all tasks have been done&lt;br /&gt;      Thread.Sleep(1);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // show the return values after all threads finished&lt;br /&gt;   tasks.ForEach(t =&gt; &lt;br /&gt;      Console.WriteLine("Thread {0} returned: {1}", t.Id, t.ReturnValue));&lt;br /&gt;&lt;br /&gt;   Console.ReadKey();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// work method&lt;br /&gt;static void DoWork(object o)&lt;br /&gt;{&lt;br /&gt;   Task task = (Task)o;&lt;br /&gt;   int id = task.Id;&lt;br /&gt;&lt;br /&gt;   for (int i = 0; i &lt; 10; i++)&lt;br /&gt;   {&lt;br /&gt;      Console.WriteLine("Thread {0} is working", id);&lt;br /&gt;      // simulate some long work&lt;br /&gt;      Thread.Sleep(200);&lt;br /&gt;&lt;br /&gt;      task.ReturnValue++;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // we have to lock the monitoring variable to &lt;br /&gt;   // ensure nobody else can work with until we decremented it&lt;br /&gt;   lock (typeof(Program))&lt;br /&gt;   {&lt;br /&gt;      _workingTasks--;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;As you see, there are quiet a lot of things to keep in mind.We have to use the C# &lt;i&gt;lock&lt;/i&gt; statement to ensure a thread safe work with our monitoring variable. Usually you don't have to lock a complete &lt;i&gt;System.Type&lt;/i&gt;; you can use &lt;i&gt;lock(this)&lt;/i&gt; or any other reference type. I just used &lt;i&gt;lock(typeof(Program))&lt;/i&gt; because I worked with static methods.We use &lt;i&gt;Thread.Sleep(1)&lt;/i&gt; to to poll the state of the dispatched tasks.Now we'll start to simplify this work.&lt;/div&gt;&lt;span style="font-size: large;"&gt;Using volatile&lt;/span&gt;&lt;div style="text-align: justify;"&gt;The first thing we can do to slightly simplify our method is to define our monitoring variable as&lt;/div&gt;&lt;pre style="background-color: #dddddd; color: #333333; font-size: 100%; line-height: 1em;"&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;static &lt;u&gt;&lt;b&gt;volatile&lt;/b&gt;&lt;/u&gt; int _workingTasks;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;The &lt;i&gt;volatile&lt;/i&gt; keyword can be used to tell .NET that a variable might be accessed by many threads for write access. If you define a member variable as volatile, you don't have to use &lt;i&gt;lock&lt;/i&gt; to ensure thread safeness.Since we used &lt;i&gt;lock&lt;/i&gt; just once in our previous sample this just changes the call of&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;lock (typeof(Program))&lt;br /&gt;{&lt;br /&gt;   _workingTasks--;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;to this&lt;/div&gt;&lt;pre style="background-color: #dddddd; color: #333333; font-size: 100%; line-height: 1em;"&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;_workingTasks--;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Seems to be senseless to work with volatile? Keep in mind, this is a very very simple sample. Not to need &lt;i&gt;lock&lt;/i&gt; becomes really handy if you have to do different things with shared member fields.&lt;/div&gt;&lt;span style="font-size: large;"&gt;Avoid the explicit Polling&lt;/span&gt;&lt;div style="text-align: justify;"&gt;The next thing to simplify your multi-threading is to remove the explicit polling. What does this mean? Since now we worked with a member field "_workingTasks" which monitored the state of our working threads. Suggest a larger class with several multi-threading implementations. In this case you would need several member fields to monitor the different threading activities. Another way to wait for the execution of a thread is to &lt;i&gt;Join()&lt;/i&gt; it.&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;   // count of tasks to be simulated&lt;br /&gt;   int taskCount = 10;&lt;br /&gt;   // hold the dispated tasks to work with the results&lt;br /&gt;   List&lt;task&gt; tasks = new List&lt;task&gt;(taskCount);&lt;br /&gt;   // remember all threads&lt;br /&gt;   List&lt;thread&gt; threads = new List&lt;thread&gt;(taskCount);&lt;br /&gt;&lt;br /&gt;   for (int i = 0; i &lt; taskCount; i++)&lt;br /&gt;   {&lt;br /&gt;      // create and remember a new thread&lt;br /&gt;      Thread thread = new Thread(new ParameterizedThreadStart(DoWork));&lt;br /&gt;      threads.Add(thread);&lt;br /&gt;&lt;br /&gt;      // create and remember the task&lt;br /&gt;      Task task = new Task { Id = i };&lt;br /&gt;      tasks.Add(task);&lt;br /&gt;      // start the thread&lt;br /&gt;      thread.Start(task);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // --&amp;gt; HERE &amp;lt;--&lt;br /&gt;   // wait until all threads are finished&lt;br /&gt;   threads.ForEach(thread =&gt; thread.Join());&lt;br /&gt;&lt;br /&gt;   // show the return values after all threads finished&lt;br /&gt;   tasks.ForEach(task =&gt;&lt;br /&gt;      Console.WriteLine(&lt;br /&gt;         "Thread {0} returned: {1}", &lt;br /&gt;         task.Id, &lt;br /&gt;         task.ReturnValue));&lt;br /&gt;&lt;br /&gt;   Console.ReadKey();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// work method&lt;br /&gt;static void DoWork(object o)&lt;br /&gt;{&lt;br /&gt;   Task task = (Task)o;&lt;br /&gt;   int id = task.Id;&lt;br /&gt;&lt;br /&gt;   for (int i = 0; i &lt; 10; i++)&lt;br /&gt;   {&lt;br /&gt;      Console.WriteLine("Thread {0} is working", id);&lt;br /&gt;      // simulate some long work&lt;br /&gt;      Thread.Sleep(200);&lt;br /&gt;&lt;br /&gt;      task.ReturnValue++;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;As you see, we don't need our monitoring variable any more. The usage of &lt;i&gt;Join()&lt;/i&gt; makes it possible to implement a much more encapsulated multi-threading.&lt;/div&gt;&lt;span style="font-size: large;"&gt;Working with the ThreadPool&lt;/span&gt;&lt;div style="text-align: justify;"&gt;Keep in mind, threads are a system resource which are important to create. If you have to do many smaller tasks it can be more expensive to create all the threads instead work single-threaded. If you have complex tasks which probably have to handle their thread state in conjunction with your application thread or other threads, you should use the &lt;i&gt;System.Threading.Thread&lt;/i&gt; class because it gives you the largest flexibility. If you just have to dispatch tasks and wait for them (as in our sample) it can be the wrong way always to create a new thread. A good approach to work with threads in this scenario is to reuse them for the next tasks.Q: Okay, cool!! Let's start to code a custom thread manager!A: Er... nope. It's already available.For this kind of work we have to do with our "Task" objects you can use the &lt;i&gt;System.Threading.ThreadPool&lt;/i&gt; class and it's especially made for this kind of work. It's a pool of threads which can be used to schedule working tasks within.To schedule means you can store a larger count of small jobs within. Whenever a pooled thread is available the next scheduled (queued) task will be started. By default .NET determines the count of initially available threads by your environment information. It also starts new threads if they seem to be useful. However, you can customize all this information by static methods (e.g. &lt;i&gt;ThreadPool.GetMaxThreads&lt;/i&gt;, &lt;i&gt;ThreadPool.SetMinThreads&lt;/i&gt;).So let's use the ThreadPool to do our tasks. For this propose I extended our "Task" class with an additional property.&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;class Task&lt;br /&gt;{&lt;br /&gt;   public int Id { get; set; }&lt;br /&gt;   public int ReturnValue { get; set; }&lt;br /&gt;   public AutoResetEvent AutoResetEvent { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;The &lt;i&gt;AutoResetEvent&lt;/i&gt; is a special type of a &lt;i&gt;WaitHandle&lt;/i&gt; which provides some special methods for multi-threading tasks.&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;   // count of tasks to be simulated&lt;br /&gt;   int taskCount = 10;&lt;br /&gt;   // hold the dispated tasks to work with the results&lt;br /&gt;   List&lt;task&gt; tasks = new List&lt;task&gt;(taskCount);&lt;br /&gt;&lt;br /&gt;   for (int i = 0; i &lt; taskCount; i++)&lt;br /&gt;   {&lt;br /&gt;      // create and remember the task&lt;br /&gt;      Task task = &lt;br /&gt;         new Task &lt;br /&gt;         { &lt;br /&gt;            Id = i, &lt;br /&gt;            AutoResetEvent = new AutoResetEvent(false) &lt;br /&gt;         };&lt;br /&gt;      tasks.Add(task);&lt;br /&gt;&lt;br /&gt;      // queue the task in ThreadPool&lt;br /&gt;      ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), task);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // wait until all queued tasks are finished&lt;br /&gt;   tasks.ForEach(task =&gt; task.AutoResetEvent.WaitOne());&lt;br /&gt;&lt;br /&gt;   // show the return values after all threads finished&lt;br /&gt;   tasks.ForEach(task =&gt;&lt;br /&gt;      Console.WriteLine(&lt;br /&gt;         "Thread {0} returned: {1}", &lt;br /&gt;         task.Id, &lt;br /&gt;         task.ReturnValue));&lt;br /&gt;&lt;br /&gt;   Console.ReadKey();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// work method&lt;br /&gt;static void DoWork(object o)&lt;br /&gt;{&lt;br /&gt;   Task task = (Task)o;&lt;br /&gt;   int id = task.Id;&lt;br /&gt;&lt;br /&gt;   for (int i = 0; i &lt; 10; i++)&lt;br /&gt;   {&lt;br /&gt;      Console.WriteLine("Thread {0} is working", id);&lt;br /&gt;      // simulate some long work&lt;br /&gt;      Thread.Sleep(200);&lt;br /&gt;      &lt;br /&gt;      task.ReturnValue++;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // notify the application thread that the task finished&lt;br /&gt;   task.AutoResetEvent.Set();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;As you see, we don't need the monitoring member fields any more. We even don't need a &lt;i&gt;Thread&lt;/i&gt; object any more. The &lt;i&gt;AutoResetEvent&lt;/i&gt; class provides a &lt;i&gt;WaitOne()&lt;/i&gt; method which can be used by our application thread to wait until all tasks finished. To release the wait handle of a &lt;i&gt;AutoResetEvent&lt;/i&gt; you can use the &lt;i&gt;Set()&lt;/i&gt; method.&lt;span style="font-size: large;"&gt;Conclusion&lt;/span&gt;&lt;div style="text-align: justify;"&gt;I hope I could show you some tricks how to simplify the work with multiple threads in your application.Almost every new computer has two or more CPUs, start to use them ;-).&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-7023951797495057434?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/7023951797495057434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2009/10/easy-working-with-threads.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7023951797495057434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/7023951797495057434'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2009/10/easy-working-with-threads.html' title='Easy Working with Threads'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-8913952302810134889</id><published>2009-10-04T13:41:00.000-07:00</published><updated>2009-11-21T08:08:07.946-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='Typed DataSets'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><title type='text'>How to handle SQL Server IDENTITIES in .NET</title><content type='html'>&lt;div style="text-align: justify;"&gt;Many people still don't use SQL Server &lt;i&gt;IDENTITY&lt;/i&gt; columns to generate their primary key values. Most times they just don't know how to handle them in client applications. In this case implementations often end up with client side ID generations or GUID primary keys. This post tries to show why server side IDs are a good approach and how to work with.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;IDENTITY is not a Sequence&lt;/span&gt;&lt;br /&gt;First I have to say, &lt;i&gt;IDENTITY&lt;/i&gt; columns are not made to represent a sequence which can/shall be shown to the user. What does this mean? Every ID is used exactly once, when you delete an existing ID it will not be reused for the next inserted row.&lt;br /&gt;&lt;br /&gt;Here's a little sample to show this behavior.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: sql;"&gt;DECLARE @t TABLE&lt;br /&gt;(&lt;br /&gt;   Id INT IDENTITY(1,1) &lt;br /&gt;      PRIMARY KEY CLUSTERED&lt;br /&gt;   ,SomeInt INT&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;-- insert some rows&lt;br /&gt;INSERT INTO @t (SomeInt) &lt;br /&gt;   VALUES (100)&lt;br /&gt;         ,(100)&lt;br /&gt;         ,(100);&lt;br /&gt;&lt;br /&gt;SELECT * FROM @t;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Since now the data appear to have a correct sequence.&lt;br /&gt;&lt;/div&gt;&lt;table border="1" rules="groups"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Id&lt;br /&gt;&lt;/th&gt;&lt;th&gt;SomeInt&lt;br /&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody style="text-align: right;"&gt;&lt;tr&gt;&lt;td&gt;1&lt;br /&gt;&lt;/td&gt;&lt;td&gt;100&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;br /&gt;&lt;/td&gt;&lt;td&gt;100&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;br /&gt;&lt;/td&gt;&lt;td&gt;100&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;div style="text-align: justify;"&gt;Let's delete one row and add another one.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: sql;"&gt;-- delete one row in the middle of the table&lt;br /&gt;-- and insert another one&lt;br /&gt;DELETE FROM @t WHERE Id = 2;&lt;br /&gt;&lt;br /&gt;INSERT INTO @t (SomeInt) &lt;br /&gt;   VALUES (200);&lt;br /&gt;&lt;br /&gt;SELECT * FROM @t;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;As you see the deleted Id with value "2" will not be refilled with the new inserted row. The Id "2" was used, deleted and will never be reused by SQL Server (without using tricks like &lt;i&gt;IDENTITY_INSERT&lt;/i&gt; or re-seed the &lt;i&gt;IDENTITY&lt;/i&gt;).&lt;br /&gt;&lt;/div&gt;&lt;table border="1" rules="groups"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Id&lt;br /&gt;&lt;/th&gt;&lt;th&gt;SomeInt&lt;br /&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody style="text-align: right;"&gt;&lt;tr&gt;&lt;td&gt;1&lt;br /&gt;&lt;/td&gt;&lt;td&gt;100&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;br /&gt;&lt;/td&gt;&lt;td&gt;100&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;br /&gt;&lt;/td&gt;&lt;td&gt;200&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;div style="text-align: justify;"&gt;Why doesn't SQL Server decrement the ID "3" when "2" became deleted? &lt;br /&gt;This would be a huge overhead for the database server. Adopt a table with 1,000,000 rows and delete ID "1". This would cause 999,999 rows to be decremented.&lt;br /&gt;&lt;br /&gt;Why doesn't SQL Server reuse the ID "3" for the next inserted row?&lt;br /&gt;In this case SQL Server would have to remember each deleted ID. This would affect the INSERT performance and the storage usage.&lt;br /&gt;&lt;br /&gt;If you need a dense rank or a sequence without any gaps you can use functions like ROW_NUMBER() or DENSE_RANK() in your select statement. Anyway, usually this kind of sequences should be handled in client if possible. It's quiet simple to use a &lt;i&gt;int&lt;/i&gt; variable to create a sequence to show in GUI.&lt;br /&gt;&lt;/div&gt;&lt;span style="font-size: large;"&gt;Client Side ID Generation&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Before we start with server side IDs, let's have a short look to the client side approaches.&lt;br /&gt;&lt;br /&gt;One solution I've seen some times is a &lt;i&gt;SELECT MAX(Id) FROM ...&lt;/i&gt; before execution of the &lt;i&gt;INSERT&lt;/i&gt; statement. This has two huge problems! First, this is a huge performance problem since every INSERT causes an index &lt;b&gt;scan&lt;/b&gt;. The second problem is, this solution is not safe. Keep in mind, a database server is a multi-user environment. Between your MAX select and the INSERT statement another user can INSERT the same ID and you get a primary key violation!&lt;br /&gt;&lt;br /&gt;A second solution to handle client side IDs is to use a ID table which contains the next available. The client applications use this table to get the next IDs for their INSERT statements. This way to handle client side IDs is a good approach but needs a correct implementation. What does this mean? Suppose a table like this:&lt;br /&gt;&lt;/div&gt;&lt;table border="1" rules="groups"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;table_name&lt;br /&gt;&lt;/th&gt;&lt;th&gt;next_id&lt;br /&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody style="text-align: right;"&gt;&lt;tr&gt;&lt;td&gt;Table1&lt;br /&gt;&lt;/td&gt;&lt;td&gt;344828&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Table2&lt;br /&gt;&lt;/td&gt;&lt;td&gt;6454&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Table3&lt;br /&gt;&lt;/td&gt;&lt;td&gt;23432&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;div style="text-align: justify;"&gt;If every client application selects &lt;b&gt;one&lt;/b&gt; ID whenever it wants to insert a new row into a table, the whole system meets in one single table with just some rows, which are probably stored in same data and index page. The result would be a problem with locks on this table.&lt;br /&gt;&lt;br /&gt;A correct solution to work with a ID table would be to use a client side ID caching. Every client selects a range of IDs to work with for the next INSERT statements. The cache size depends on the type of the client and the count of INSERT operations generated by this client. A windows application which does not generate too many new rows might be fine with a cache size of 10, a server side import process probably needs a cache size of 500 IDs or more.&lt;br /&gt;&lt;br /&gt;Doesn't this mean that cached IDs will not be used if the client application exists when IDs are cached? Yes, but this doesn't matter. Keep in mind, primary key IDs are &lt;b&gt;not&lt;/b&gt; made to show to a user. They are the database identity of a row. Since &lt;i&gt;INT&lt;/i&gt; has a maximum value of 2,147,483,647 this should be enough for most systems - even if you loose some IDs. If you think you might exceed this count of IDs you can use &lt;i&gt;BIGINT&lt;/i&gt; which has a maximum value of 9,223,372,036,854,775,807.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Database Structure&lt;/span&gt;&lt;br /&gt;Before we start with server side &lt;i&gt;IDENTITIES&lt;/i&gt;, you should know the database structure for the following tests.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_hBTxNhEL4oY/SshlsroZkqI/AAAAAAAAAAM/5CXPRVU4IEk/s1600-h/database_structure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_hBTxNhEL4oY/SshlsroZkqI/AAAAAAAAAAM/5CXPRVU4IEk/s320/database_structure.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;And here the create statements for both tables.&lt;br /&gt;&lt;pre class="brush: sql;"&gt;CREATE TABLE Parent&lt;br /&gt;(&lt;br /&gt; Id int IDENTITY(1,1) NOT NULL&lt;br /&gt;    PRIMARY KEY CLUSTERED&lt;br /&gt; ,SomeInt int NULL&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;CREATE TABLE Child&lt;br /&gt;(&lt;br /&gt;   Id int IDENTITY(1,1) NOT NULL&lt;br /&gt;      PRIMARY KEY CLUSTERED&lt;br /&gt;   ,ParentId int NOT NULL&lt;br /&gt;      REFERENCES Parent (Id)&lt;br /&gt;   ,SomeInt int NULL&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;As you see, both tables have an &lt;i&gt;IDENTITY&lt;/i&gt; column defined as primary key and "Child" table has a foreign key which points to "Parent" table.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Low Level ADO.NET&lt;/span&gt;&lt;br /&gt;First we'll have a look to the low level way to work with server side IDs. Therefore we use a &lt;i&gt;SqlCommand&lt;/i&gt; to execute an &lt;i&gt;INSERT&lt;/i&gt; statement and retrieve the new id from server.&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;string cnStr = "Server=.;Database=Sandbox;Integrated Security=SSPI;";&lt;br /&gt;&lt;br /&gt;// the INSERT sql statement. Notice the "SELECT @Id"!&lt;br /&gt;string insertSql = @"INSERT INTO Parent (SomeInt) &lt;br /&gt;                        VALUES (@SomeInt); &lt;br /&gt;                     SELECT @Id = SCOPE_IDENTITY();";&lt;br /&gt;&lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr))&lt;br /&gt;using (SqlCommand insertCmd = new SqlCommand(insertSql, cn))&lt;br /&gt;{&lt;br /&gt;   cn.Open();&lt;br /&gt;&lt;br /&gt;   // Add the @SomeInt param with a value&lt;br /&gt;   SqlParameter someIntParam = insertCmd.Parameters.Add(&lt;br /&gt;      "@SomeInt", SqlDbType.Int);&lt;br /&gt;   someIntParam.Value = 123;&lt;br /&gt;   &lt;br /&gt;   // Add the @Id param and define it as output parameter&lt;br /&gt;   SqlParameter idParam = insertCmd.Parameters.Add(&lt;br /&gt;      "@Id", SqlDbType.Int);&lt;br /&gt;   idParam.Direction = ParameterDirection.Output;&lt;br /&gt;&lt;br /&gt;   // execute the command&lt;br /&gt;   insertCmd.ExecuteNonQuery();&lt;br /&gt;&lt;br /&gt;   // show the "Id" after the data are written to server&lt;br /&gt;   Console.WriteLine("after database insert: {0}", idParam.Value);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Since our "idParam" is specified as output parameter ADO retrieves the new &lt;i&gt;SCOPE_IDENTITY()&lt;/i&gt; from server and we can work with it in our client.&lt;br /&gt;&lt;br /&gt;Mostly we don't need to work with this low level implementations. Anyway, sometimes it's good to know how the upper level works.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Working with untyped DataTables&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Still quiet low level but common. I've seen many solutions working with untyped DataTables to handle data from a database server. Usually I would say use at least typed DataSets or an O/R-mapper. Anyway. ;-)&lt;br /&gt;&lt;br /&gt;How to handle server side IDs with a DataTable? The DataTable will be updated with a &lt;i&gt;SqlDataAdapter&lt;/i&gt;, so there is no way to customize the parameters and handle the returned values, is there? To combine the columns of a DataTable with return values of a &lt;i&gt;SqlParameter&lt;/i&gt; you can use the &lt;i&gt;SqlParameter.SourceColumn&lt;/i&gt; property, which specifies the mapping between the parameter and the columns of the table.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: csharp;"&gt;string cnStr = "Server=.;Database=Sandbox;Integrated Security=SSPI;";&lt;br /&gt;&lt;br /&gt;// the INSERT sql statement. Notice the "SELECT @Id"!&lt;br /&gt;string insertSql = @"INSERT INTO Parent (SomeInt) &lt;br /&gt;                        VALUES (@SomeInt); &lt;br /&gt;                     SELECT @Id = SCOPE_IDENTITY();";&lt;br /&gt;&lt;br /&gt;using (SqlConnection cn = new SqlConnection(cnStr))&lt;br /&gt;using (SqlCommand insertCmd = new SqlCommand(insertSql, cn))&lt;br /&gt;using (SqlDataAdapter adap = new SqlDataAdapter())&lt;br /&gt;{&lt;br /&gt;   // create a DataTable which represents our Parent table&lt;br /&gt;   DataTable table = new DataTable();&lt;br /&gt;   // specify Id columnd as AutoIncrement&lt;br /&gt;   table.Columns.Add("Id", typeof(int)).AutoIncrement = true;&lt;br /&gt;   table.Columns.Add("SomeInt", typeof(int));&lt;br /&gt;&lt;br /&gt;   // Add a row to our table and show the current Id value (which is "0")&lt;br /&gt;   DataRow row = table.Rows.Add(null, 1);&lt;br /&gt;   Console.WriteLine("before database insert: {0}", row["Id"]);&lt;br /&gt;&lt;br /&gt;   // add the "SomeInt" param&lt;br /&gt;   insertCmd.Parameters.Add("@SomeInt", SqlDbType.Int, 4, "SomeInt");&lt;br /&gt;   // add the "Id" param and define it as output param&lt;br /&gt;   SqlParameter idParam = insertCmd.Parameters.Add(&lt;br /&gt;      "@Id", SqlDbType.Int, 4, "Id");&lt;br /&gt;   idParam.Direction = ParameterDirection.Output;&lt;br /&gt;&lt;br /&gt;   // inject the adapter with the custom command and update data&lt;br /&gt;   adap.InsertCommand = insertCmd;&lt;br /&gt;   adap.Update(table);&lt;br /&gt;&lt;br /&gt;   // show the "Id" after the data are written to server&lt;br /&gt;   // this returns the new IDENTITY now.&lt;br /&gt;   Console.WriteLine("after database insert: {0}", row["Id"]);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;The fourth parameter of &lt;i&gt;SqlCommand.Parameters.Add&lt;/i&gt; specifies the "SourceColumn". The data adapter uses this column to create the mapping between the parameters and the columns of the table to be updated. The console output shows the server side generated value of our "Id" column.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Working with typed DataSets&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Welcome on "it works build in" level. Maybe some of you made bad experiences with &lt;i&gt;IDENTITY&lt;/i&gt; columns and typed DataSets, let me tell you that's just caused of a tiny configuration issue within the DataSet designer.&lt;br /&gt;&lt;br /&gt;If you already used the previously shown &lt;i&gt;CREATE&lt;/i&gt; statements to create the sample tables "Parent" and "Child" on a sample database just create a typed DataSet named "DataSet1" in a Visual Studio C# project. You will find some detailed tutorials in MSDN, which show hot to handle this. Here I just want to show how to configure a correct handling of &lt;i&gt;IDENTITY&lt;/i&gt; columns.&lt;br /&gt;&lt;br /&gt;Have a look to the DataSet1.Designer.cs file and navigate to the &lt;i&gt;ParentTableAdapter&lt;/i&gt;. You will find the following line in "InitAdapter()" method.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: csharp;"&gt;this._adapter.InsertCommand.CommandText = &lt;br /&gt;   "INSERT INTO [dbo].[Parent] ([SomeInt]) VALUES (@SomeInt);\r\n" +&lt;br /&gt;   &lt;b&gt;"SELECT Id, SomeInt FROM Parent WHERE (Id = SCOPE_IDENTITY())";&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;As you see, it selects all inserted values back to client as soon as the new row is inserted. Unfortunately, in default configuration the selected "Id" value will not be written to our related &lt;i&gt;ChildDataTable&lt;/i&gt;. Go back to the DataSet Designer and do the following tasks:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Right click the relation between "Parent" and "Child" table and select "Edit Relation...". The relation configuration dialog appears.&lt;/li&gt;&lt;li&gt;In section "Choose what to create" select option "Both Relation and Foreign Key Constraint".&lt;/li&gt;&lt;li&gt;Change "Update Rule" to "Cascade".&lt;/li&gt;&lt;li&gt;Ensure "Accept/Reject Rule" is set to "None". If you change this option to "Cascade", the changes of our "Child" row will be automatically when the "Parent" table becomes saved.&lt;/li&gt;&lt;/ul&gt;The following picture shows the configuration.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_hBTxNhEL4oY/SsoyHisXsII/AAAAAAAAAAc/6jXg-WQw42U/s1600-h/DataSet_Relation.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_hBTxNhEL4oY/SsoyHisXsII/AAAAAAAAAAc/6jXg-WQw42U/s320/DataSet_Relation.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Finally a little sample which can be copied and pasted to illustrate the correct identity handling with a typed DataSet.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: csharp;"&gt;// create a DataSet&lt;br /&gt;DataSet1 ds = new DataSet1();&lt;br /&gt;&lt;br /&gt;// get the parent table and add a new row&lt;br /&gt;DataSet1.ParentDataTable parentTable = ds.Parent;&lt;br /&gt;DataSet1.ParentRow parentRow = parentTable.AddParentRow(1);&lt;br /&gt;&lt;br /&gt;// get the child table and add a new row&lt;br /&gt;DataSet1.ChildDataTable childTable = ds.Child;&lt;br /&gt;DataSet1.ChildRow childRow = childTable.AddChildRow(parentRow, 1);&lt;br /&gt;&lt;br /&gt;// create the table adapters&lt;br /&gt;DataSet1TableAdapters.ParentTableAdapter parentAdapter =&lt;br /&gt;   new ConsoleApplication2.DataSet1TableAdapters.ParentTableAdapter();&lt;br /&gt;DataSet1TableAdapters.ChildTableAdapter childAdapter =&lt;br /&gt;   new ConsoleApplication2.DataSet1TableAdapters.ChildTableAdapter();&lt;br /&gt;&lt;br /&gt;// update the parent table&lt;br /&gt;parentAdapter.Update(parentTable);&lt;br /&gt;// #######################&lt;br /&gt;// At this point, the new IDENTITY value from parent row&lt;br /&gt;// was written to our child row!&lt;br /&gt;// #######################&lt;br /&gt;Console.WriteLine(childRow.ParentId);&lt;br /&gt;&lt;br /&gt;childAdapter.Update(childTable);&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Special thanks at this point goes to &lt;a href="http://home.arcor.de/eckardahlers/Programmer/Downloadpage/index.html"&gt;ErfinderDesRades&lt;/a&gt;, a power-user state member of &lt;a href="http://www.mycsharp.de/"&gt;myCSharp.de&lt;/a&gt; - a great C# forum. He showed me the correct configuration of the &lt;i&gt;DataSet&lt;/i&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;LINQ 2 SQL and Entities Framework&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;LINQ 2 SQL as well as Entities Framework support &lt;i&gt;IDENTITY&lt;/i&gt; columns out of the box, so there is nothing more to say about these O/R mappers.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6936017315111598402-8913952302810134889?l=florianreischl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://florianreischl.blogspot.com/feeds/8913952302810134889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://florianreischl.blogspot.com/2009/10/how-to-handle-sql-server-identities-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/8913952302810134889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6936017315111598402/posts/default/8913952302810134889'/><link rel='alternate' type='text/html' href='http://florianreischl.blogspot.com/2009/10/how-to-handle-sql-server-identities-in.html' title='How to handle SQL Server IDENTITIES in .NET'/><author><name>Florian Reischl</name><uri>http://www.blogger.com/profile/09186266704215711060</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://3.bp.blogspot.com/_hBTxNhEL4oY/TEvYewYa3wI/AAAAAAAAAF8/BDaKeKowc58/S220/florian_reischl.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_hBTxNhEL4oY/SshlsroZkqI/AAAAAAAAAAM/5CXPRVU4IEk/s72-c/database_structure.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6936017315111598402.post-3598524762646042218</id><published>2009-09-26T14:35:00.000-07:00</published><updated>2009-11-21T05:37:29.745-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL CLR'/><category scheme='http://www.blogger.com/atom/ns#' term='split strings'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>High Performance String Split Functions</title><content type='html'>&lt;div style="text-align: justify;"&gt;To split a string into pieces is a quiet common task in T-SQL and there are many different solutions to handle this. So, why yet another one? This article should not only show yet another way to split strings, but it tries to compare all the different approaches. Before the competition starts, let me present the participants.&lt;br /&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;WHILE Loop&lt;/li&gt;&lt;li&gt;Numbers Table&lt;/li&gt;&lt;li&gt;XML&lt;/li&gt;&lt;li&gt;SQL CLR&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;First I want to show you the different approaches. At the end of the article I'll show you some performance comparisons.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;WHILE Loop&lt;/span&gt;&lt;br /&gt;If you search the internet for functions to split strings you will primary find solutions based on &lt;i&gt;WHILE&lt;/i&gt; loops. Since this is the most common approach we should start with it.&lt;br /&gt;&lt;br /&gt;How does the cursor work?&lt;br /&gt;&lt;br /&gt;The common topology is to start at the first position of the string and search the first occurrence of the specified separator by using &lt;i&gt;CHARINDEX&lt;/i&gt;. Now use &lt;i&gt;SUBSTRING&lt;/i&gt; to get the first item from position 1 to the first found separator position; now find the next item starting at the previously found position and so on.&lt;br /&gt;Other versions work with &lt;i&gt;PATINDEX&lt;/i&gt; instead of &lt;i&gt;CHARINDEX&lt;/i&gt; but this is much slower and not needed for the requirement.&lt;br /&gt;&lt;br /&gt;This should be a quiet fast &lt;i&gt;WHILE&lt;/i&gt; loop based solution.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: sql;"&gt;IF (OBJECT_ID('tvf_SplitString_Cursor') IS NULL)&lt;br /&gt;   EXECUTE('CREATE FUNCTION tvf_SplitString_Cursor() &lt;br /&gt;            RETURNS @t TABLE (Id INT) AS &lt;br /&gt;            BEGIN INSERT INTO @t VALUES(1) &lt;br /&gt;            RETURN END');&lt;br /&gt;GO&lt;br /&gt;ALTER FUNCTION tvf_SplitString_Cursor&lt;br /&gt;(&lt;br /&gt;   @text NVARCHAR(MAX), &lt;br /&gt;   @separator NVARCHAR(255)&lt;br /&gt;)&lt;br /&gt;   RETURNS @ReturnData TABLE (Item NVARCHAR(4000))&lt;br /&gt;AS&lt;br /&gt;BEGIN&lt;br /&gt;   DECLARE &lt;br /&gt;      @pos           INT&lt;br /&gt;      ,@next         INT&lt;br /&gt;      ,@separatorLen INT = LEN(@separator);&lt;br /&gt;   &lt;br /&gt;&lt;br /&gt;   -- Get the first occurence to get the item before the first delimiter&lt;br /&gt;   SELECT @pos = CHARINDEX(@separator, @text, 1);&lt;br /&gt;   &lt;br /&gt;   -- Insert the first item&lt;br /&gt;   INSERT INTO @ReturnData&lt;br /&gt;      SELECT SUBSTRING(@text, 1, @pos - 1);&lt;br /&gt;   &lt;br /&gt;   -- Step over the first delimiter&lt;br /&gt;   SELECT @pos = @pos + @separatorLen;&lt;br /&gt;&lt;br /&gt;   WHILE (1 = 1)&lt;br /&gt;   BEGIN&lt;br /&gt;      -- Get the next delimiter position from our previous position&lt;br /&gt;      SELECT @next = CHARINDEX(@separator, @text, @pos);&lt;br /&gt;      &lt;br /&gt;      IF (@next = 0) BREAK -- nothing more to do&lt;br /&gt;&lt;br /&gt;      -- Insert the next found item&lt;br /&gt;      INSERT INTO @ReturnData&lt;br /&gt;         SELECT SUBSTRING(@text, @pos, @next - @pos);&lt;br /&gt;&lt;br /&gt;      -- Step of the delimiter&lt;br /&gt;      SELECT @pos = @next + @separatorLen;&lt;br /&gt;   END&lt;br /&gt;&lt;br /&gt;   -- Due to the fact that our cursor only jumps from delimter &lt;br /&gt;   -- to delimiter the last item would be lost&lt;br /&gt;   INSERT INTO @ReturnData&lt;br /&gt;      SELECT SUBSTRING(@text, @pos, LEN(@text) - 1);&lt;br /&gt;&lt;br /&gt;   RETURN;&lt;br /&gt;END&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Numbers Table&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;A Numbers table is a table which contains incremental numbers from 1 to N, where N depends on your requirements to the table. This tables can be used for different solutions, as I showed &lt;a href="http://florianreischl.blogspot.com/2009/09/numbers-table.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The following script is based on Jeff Moden's great article &lt;a href="http://www.sqlservercentral.com/articles/T-SQL/62867/"&gt;The "Numbers" or "Tally" Table: What it is and how it replaces a loop&lt;/a&gt; at &lt;a href="http://www.sqlservercentral.com/"&gt;SQLServerCentral.com&lt;/a&gt;. I don't want to say "It's my idea".&lt;br /&gt;&lt;br /&gt;How can I use a Numbers table to split a string?&lt;br /&gt;&lt;br /&gt;The general idea is to transform the horizontal string into a vertical table where each row contains one character of the source string. The &lt;i&gt;WHERE&lt;/i&gt; clause is used to return only the specified separators. Whenever we reach a separator we use &lt;i&gt;SUBSTRING&lt;/i&gt; to extract the item from the current position to the next occurrence of the separator. To determine the next position of the separator we use &lt;i&gt;CHARINDEX&lt;/i&gt;, just like the &lt;i&gt;WHILE&lt;/i&gt; loop based approach.&lt;br /&gt;&lt;br /&gt;Here is a sample, how to use a Numbers table to split a string into pieces.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: sql;"&gt;DECLARE &lt;br /&gt;   @text VARCHAR(100)      = ',a,b,c,'&lt;br /&gt;   ,@separator CHAR(1)     = ',';&lt;br /&gt;&lt;br /&gt;SELECT&lt;br /&gt;   -- Extract the current part from specified string&lt;br /&gt;   -- Start position is the current position within the numbers table &lt;br /&gt;   --    plus the length of the separator&lt;br /&gt;   -- The length is the next position of the separator minus the&lt;br /&gt;   --    current position and the len of the separator&lt;br /&gt;   SUBSTRING(&lt;br /&gt;      @text&lt;br /&gt;      ,t.Num + LEN(@separator)&lt;br /&gt;      ,CHARINDEX(@separator, @text, t.Num + 1) - t.Num - LEN(@separator)&lt;br /&gt;      ) AS Item&lt;br /&gt;FROM dbo.Numbers t&lt;br /&gt;WHERE &lt;br /&gt;   -- Scan only until the length of the text - 1 &lt;br /&gt;   -- to avoid wrong parameter for SUBSTRING&lt;br /&gt;   t.Num &amp;lt; LEN(@text)&lt;br /&gt;   -- The current item has to match to the specified delimiter&lt;br /&gt;   AND SUBSTRING(@text, t.Num, LEN(@separator)) = @separator&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;If you want to use a Numbers table to split strings you have to keep two important things in mind. The first thing is, the source string always needs to be enclosed with a leading and trailing separator. This depends on the topology of the approach to get the items &lt;b&gt;between&lt;/b&gt; the separators. As second you have to ensure that your Numbers table contains enough rows. The count of rows has to be at least the maximal length of the source strings plus two separators. A way to ensure a Numbers table with enough rows is to use a common table expression (CTE) in this case.&lt;br /&gt;&lt;/div&gt;&lt;pre class="brush: sql;"&gt;WITH &lt;br /&gt;n1 (Num) AS (SELECT 1 UNION ALL SELECT 1),   -- 2&lt;br /&gt;n2 (Num) AS (SELECT a.Num FROM n1 a, n1 b),  -- 4&lt;br /&gt;n3 (Num) AS (SELECT a.Num FROM n2 a, n2 b),  -- 16&lt;br /&gt;n4 (Num) AS (SELECT a.Num FROM n3 a, n3 b),  -- 256&lt;br /&gt;n5 (Num) AS (SELECT a.Num FROM n4 a, n4 b),  -- 65536&lt;br /&gt;-- 4.294.967.296&lt;br /&gt;Numbers (Num) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) &lt;br /&gt;                  FROM n5 a, n5 b)&lt;br /&gt;SELECT&lt;br /&gt;      *&lt;br /&gt;   FROM Numbers&lt;br /&gt;   WHERE Num &lt; 100000;&lt;br /&gt;&lt;/pre&gt;This provides a Numbers table with up to 4.294.967.296 which fits for string with up to 4GB.&lt;span style="font-size: large;"&gt;XML&lt;/span&gt;&lt;div style="text-align: justify;"&gt;Some solutions to split a string are based on a conversion to XML to use XQuery to extract the items. Sounds strange? It is ;-).How can I do that?To split a string using XML first you have to convert the source string into a XML data type and replace the specified separator with XML tags. After that you can use XQuery to get the items within the string.The following script shows how to work with XML to split strings.&lt;/div&gt;&lt;pre class="brush: sql;"&gt;DECLARE &lt;br /&gt;   @text VARCHAR(100)      = 'a,b,c'&lt;br /&gt;   ,@separator CHAR(1)     = ',';&lt;br /&gt;&lt;br /&gt;WITH cte (data) AS&lt;br /&gt;(&lt;br /&gt;   SELECT CONVERT(XML, '&amp;lt;y&amp;gt;' &lt;br /&gt;                       + REPLACE(@text, @separator, '&amp;lt;/y&amp;gt;&amp;lt;y&amp;gt;') &lt;br /&gt;                       + '&amp;lt;/y&amp;gt;')&lt;br /&gt;)&lt;br /&gt;SELECT&lt;br /&gt;      T.C.value('.', 'nvarchar(2000)')&lt;br /&gt;   FROM cte&lt;br /&gt;      CROSS APPLY cte.data.nodes('y') T(C)&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;This method should work with most kind of data, but it runs into problems if the source string contains XML language elements like "&amp;lt;", "&amp;gt;" or "&amp;amp;".&lt;/div&gt;&lt;span style="font-size: large;"&gt;SQL CLR&lt;/span&gt;&lt;div style="text-align: justify;"&gt;Now the (hopefully) last possibility to split strings into pieces is to use SQL CLR.How to do?Well, there are many different ways to split a string using .NET. The simplest way would be the build in function String.Split() which is available on every instance of a System.String. The most flexible way to split a string with .NET would be a regular expression. Nevertheless we use a non build-in raw function to handle that. Why?? String.Split() is definitely a cool function but we are speaking about a function for a Server and String.Split() causes the complete string twice in memory which can affect the performance when your server in on load. Same depends on regular expressions, which is way to hungry for resources and a functional overkill to just split a string.We use a function which iterates through the complete string and searches for the specified separator. Whenever a separator is reached we use &lt;i&gt;yield return&lt;/i&gt; to return the item between the last position of a separator and and the current position. The functionality is quiet alike the &lt;i&gt;WHILE&lt;/i&gt; loop approach but enclosed within a compiled .NET assembly.Here is the body of your function.&lt;/div&gt;&lt;pre class="brush: c-sharp;"&gt;using System.Data.SqlTypes;&lt;br /&gt;using Microsoft.SqlServer.Server;&lt;br /&gt;using System.Collections;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public partial class StoredProcedures&lt;br /&gt;{&lt;br /&gt;   [Microsoft.SqlServer.Server.SqlFunction(&lt;br /&gt;      FillRowMethodName = "FillRowSplitString",&lt;br /&gt;      TableDefinition = "Item nvarchar(4000)",&lt;br /&gt;      IsDeterministic = true,&lt;br /&gt;      SystemDataAccess = SystemDataAccessKind.None&lt;br /&gt;      )&lt;br /&gt;   ]&lt;br /&gt;   public static IEnumerable SplitString(&lt;br /&gt;      [SqlFacet(MaxSize = -1, IsFixedLength=false, IsNullable=false)]&lt;br /&gt;      SqlString text,&lt;br /&gt;      [SqlFacet(MaxSize = 1, IsFixedLength = true, IsNullable = false)]&lt;br /&gt;      SqlString separator&lt;br /&gt;      )&lt;br /&gt;   {&lt;br /&gt;      // init variables&lt;br /&gt;      char s = separator.Value[0];&lt;br /&gt;      string buffer = text.Value;&lt;br /&gt;      int lastIndex = 0;&lt;br /&gt;      int len = 0;&lt;br /&gt;      int i;&lt;br /&gt;&lt;br /&gt;      // loop through the string&lt;br /&gt;      for (i = 0; i &amp;lt; buffer.Length; i++)&lt;br /&gt;      {&lt;br /&gt;         // check if the current character matches to the separator&lt;br /&gt;         if (buffer[i] == s)&lt;br /&gt;         {&lt;br /&gt;            // return the item from last and current positions&lt;br /&gt;            yield return buffer.Substring(lastIndex, len);&lt;br /&gt;            lastIndex = i + 1;&lt;br /&gt;            len = 0;&lt;br /&gt;         }&lt;br /&gt;         else&lt;br /&gt;         {&lt;br /&gt;            len++;&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      // return the last item&lt;br /&gt;      yield return buffer.Substring(lastIndex, buffer.Length - lastIndex);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // fill output row&lt;br /&gt;   public static void FillRowSplitString(&lt;br /&gt;      object obj,&lt;br /&gt;      out SqlString item&lt;br /&gt;      )&lt;br /&gt;   {&lt;br /&gt;      item = (string)obj;&lt;br /&gt;   }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-size: large;"&gt;Processing Performance&lt;/span&gt;Now, that we know all possible ways to split a string within T-SQL, let me compare the performance of the different approaches.Since the performance tests depend on the hardware, a short description of my test environment.&lt;table&gt;&lt;tr&gt;&lt;td&gt;CPU&lt;/td&gt;&lt;td&gt;Intel Quad 2.4GHz Q6600&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RAM&lt;/td&gt;&lt;td&gt;8 GB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Operating System&lt;/td&gt;&lt;td&gt;Windows Server 2008 x64 SP2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SQL Server&lt;/td&gt;&lt;td&gt;SQL Server 2008 x64 SP2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Network&lt;/td&gt;&lt;td&gt;localhost&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;It migth be quiet boring to split "a,b,c" by "," and show you zero durations for all tests. So I worked with whole table strings. The columsn of the following table mean:&lt;ul&gt;&lt;li&gt;&lt;b&gt;Item Length&lt;/b&gt;: Is the length of the resulting items within the source text.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Item count&lt;/b&gt; is the count of resulting items for each row.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Row count&lt;/b&gt; is the count of source rows which have to be handled.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Data type&lt;/b&gt; is the column type of the source table.&lt;/li&gt;&lt;/ul&gt;Here you can find a table with some of my test results.&lt;table border="1" rules="groups"&gt;&lt;thead&gt;&lt;tr style="font-weight: bold; border-top: solid 2px #000;"&gt;       &lt;th&gt;#&lt;/th&gt;    
