Wednesday, December 26, 2012

Implement GetHashCode() to track changed objects in C#

Let's say we pull information about Movies from remote XML and save it in our database. Class that represent this objects can look like:
 public class Movie  
 {  
     public int Id { get; set; }  
     public string Name { get; set; }      
     public int? Duration { get; set; }  
     public int? Director { get; set; }      
     public int[] Actors { get; set; }      
     public int[] Genres { get; set; }      
     public int[] Countries { get; set; }      
     public string PosterUrl { get; set; }  
     public double? Rate { get; set; }  
     public int? Votes { get; set; }  
     public double? Imdb { get; set; }  
     public int? ImdbVotes { get; set; }  
     public string Site { get; set; }  
     public string Limits { get; set; }  
     public DateTime? Date { get; set; }  
     public string Description { get; set; }  
     public string Trailers { get; set; }  
     public string Company { get; set; }      
 }  

Write operations are expensive if there are a lot of objects to be saved, so for performance reasons we should NOT save new object in database, if there is old object in database that is the same. So we need to extract object from databse and determine if new object differ from the old one. If objects are the same we DO NOT update it.

But how to determine that objects are the same?

Objects are differ if their contents differ. In our case we can clarify this as follows: Objects are differ if their properties are differ.

Let's override GetHashCode() and Equals() methods to define how to check equality of 2 Movie objects:
 public class Movie  
 {  
    public int Id { get; set; }  
    public string Name { get; set; }  
    public int? Duration { get; set; }  
    public int? Director { get; set; }  
    public int[] Actors { get; set; }  
    public int[] Genres { get; set; }  
    public int[] Countries { get; set; }  
    public string PosterUrl { get; set; }  
    public double? Rate { get; set; }  
    public int? Votes { get; set; }  
    public double? Imdb { get; set; }  
    public int? ImdbVotes { get; set; }  
    public string Site { get; set; }  
    public string Limits { get; set; }  
    public DateTime? Date { get; set; }  
    public string Description { get; set; }  
    public string Trailers { get; set; }  
    public string Company { get; set; }  
    
    public override int GetHashCode()  
    {  
       return HashCodeGenerator.Generate(Id, Name, Duration, Director, Actors, Genres, Countries, PosterUrl, Rate, Votes, Imdb, ImdbVotes, Site, Limits, Date, Description, Trailers, Company);  
    }  
    public override bool Equals(object obj)  
    {  
       return this.GetHashCode() == obj.GetHashCode();  
    }        
  }  

As you can see, we use custom class HashCodeGenerator to generate hash code from specified property values that we need to track.

Implementation of this class:
  public static class HashCodeGenerator  
  {  
     public static int Generate(params object[] objects)  
     {  
       unchecked  
       {  
         var offset = 13;  
         var compositionOffset = 7;  
         foreach (object obj in objects)  
         {  
           if (obj==null)  
             continue;  
           if (obj is Array)  
           {  
             var array = obj as Array;  
             foreach (var item in array)  
             {  
               offset = (offset * compositionOffset) + item.GetHashCode();  
             }  
           }  
           else  
           {  
             offset = (offset * compositionOffset) + obj.GetHashCode();  
           }            
         }            
         return offset;  
       }  
     }      
   }  

Wednesday, December 19, 2012

Using expression trees to get rid of "magic" strings in C#

"Magic" strings may appear in programming code in many cases. For example, if we need to pass property names to some method.

Let's say we need to make DatabaseIndexCreator class that creates database index for specified property name(or properties, if index is compound) of some model(in our example it's Person class):
 public class Person  
 {  
   public string Name { get; set; }  
   public string Surname { get; set; }  
   public bool Sex { get; set; }  
 }  

So, we end up with function that accept property names as strings:
 public class DatabaseIndexCreator<TEntity>  
 {  
   public void CreateIndex(string[] fields)  
   {  
     //creating index  
   }  
 }  

And use this class like this:
 DatabaseIndexCreator<Person> indexCreator = new DatabaseIndexCreator<Person>();  
 //creating simple index:  
 indexCreator.CreateIndex(new[] { "Name" });  
 //creating compound index:  
 indexCreator.CreateIndex(new[] { "Name", "Sex" });  

It's bad design, because you can forget to rename this "magic" strings after renaming properties of Person class.

But you can use Expression Trees - nice C# feature to get rid of this "magic" strings in your code.

Let's create class with extension method for Expression<Func<T, U>> expression:
  public static class ExpressionEx  
  {  
     public static HashSet<string> AsMemberExpressionKeys<T, U>(this Expression<Func <T, U>> index)  
     {  
       var exp = index.Body as NewExpression;  
       var keys = new HashSet<string>();  
       if (exp != null)  
       {  
         foreach (var x in exp.Arguments.OfType<MemberExpression>())  
         {  
           keys.Add(GetPropertyAlias(x));  
         }  
       }  
       else if (index.Body is MemberExpression)  
       {  
         var me = index.Body as MemberExpression;  
         keys.Add(GetPropertyAlias(me));  
       }  
       return keys;  
     }  
     private static string GetPropertyAlias(MemberExpression mex)  
     {  
       var retval = "";  
       var parentEx = mex.Expression as MemberExpression;  
       if (parentEx != null)  
       {  
         retval += GetPropertyAlias(parentEx) + ".";  
       }        
       retval += mex.Member.Name;  
       return retval;  
     }  
  }  

What benefits can we get from this tricky extension method?

Now we can refactor our DatabaseIndexCreator class like this:
 public class DatabaseIndexCreator<TEntity>  
 {  
   public void CreateIndex<TReturn>(Expression<Func<TEntity, TReturn>> exp)  
   {  
     string[] fields = exp.AsMemberExpressionKeys().ToArray();  
     //creating index(simple or compound)  
   }  
 }  

And use this class like this:
 DatabaseIndexCreator<Person> indexCreator = new DatabaseIndexCreator<Person>();  
 //creating simple index:  
 indexCreator.CreateIndex(t => t.Name);  
 //creating compound index:  
 indexCreator.CreateIndex(t => new {t.Name, t.Sex});  

As you see, there is no more "magic" strings, that is very good for our code design and our nerves.

Wednesday, December 12, 2012

Redirect www subdomain to root domain in ASP.NET

Let's say we want to perform permanent redirect from http://www.example.com address to http://example.com in our ASP.NET application for SEO purposes(URL canonization).

First of all, we need to download Rewrite module for IIS7:
http://www.microsoft.com/web/gallery/install.aspx?appid=urlrewrite2

Then you need to open IIS Manager and navigate to URL Rewrite section.

After proper configuration in IIS Manager you'll get section in your Web.config that can look like:
 <configuration>  
   <system.webServer>  
     <rewrite>  
       <rules>  
         <rule name ="CanonicalHostNameRule" stopProcessing="true">  
           <match url="(.*)" />  
           <conditions>  
             <add input ="{HTTP_HOST}" pattern="^www\." negate="false" />  
           </conditions>  
           <action type ="Redirect" url="http://example.com/{R:1}" />  
         </rule>  
       </rules>  
     </rewrite>  
   </system.webServer>   
 </configuration>  

Thursday, December 6, 2012

Cancelable tasks in .NET 4.0

There is new nice feature in .NET >= 4.0 - cancelling asynchronoums tasks.


Now you can do this:
 public class JobClass  
   {      
     private readonly CancellationTokenSource _cancellationSource;  
     public JobClass()  
     {  
       _cancellationSource = new CancellationTokenSource();        
     }              
     public void DoWork()  
     {  
         ...  
         Action action = () =>  
          {             
            foreach (var a in array)  
            {               
             /*do something*/  
             _cancellationSource.Token.ThrowIfCancellationRequested();  
            }  
          };  
        var task = new Task(action, _cancellationSource.Token);  
        task.Start();         
     }  
     public void Cancel()  
     {  
       _cancellationSource.Cancel();  
     }                       
   }  

As you can see, we created Task with cancellation Token. After this we can use cancellationSource to cancel this Task any time we want. It should be noted, that we use Token.ThrowIfCancellationRequested() method in async method body to throw exception if cancellation was requested.

Thursday, November 29, 2012

Hybrid CQRS implementation using MongoDb

Introduction to CQRS

Command and Query Responsibility Segregation(CQRS) is a pattern that suggests you to use different models to read and to write information.

In standard relational systems you have dilemma: use normalized database or denormalized database? In first case you get fine-designed database that is good for writing data, but has poor reading performance. In second case you get headache with your updates, but(if properly denormalized) you can get good reading performance.

So, CQRS suggests to use 2 different databases: one optimized for reading(denormalized) and another for writing(normalized). It is a very tempting way to designing systems. The only big problem with this solution is that you need somehow to sync you databases. You can create some sort of Denormalizer that would perform synchronization between your normalized and denormalized databases, after writings to your normalized database.

Is there a simpler solution?
I think there is one using NoSQL database(for example, MongoDb).

What is MongoDb?

MongoDb is a non-relational data store for JSON documents. More about MongoDb.
Big benefit of MongoDb is that it you can easily store\restore objects that you have inside your program to\from database. This help us much in our Hybrid CQRS implementation.

Hybrid CQRS implementation using MongoDb
All commands(write operations) go through Service layer where validators and other protective measures are applied. Querying(read operations) are allowed directly from Database to speed up process.

Since we use NoSQL database(MongoDb) it is not strictly necessary for us to use different databases for reading and writing. If we make proper design of our MongoDb database, it will be good for reading(due to structure of data storage) and no bad for writings(if we do not go too far with denormalization).

This CQRS implementation is applicable in cases when you want to use Domain-Driven design approach for your system Core, at the same time retaining the ability for fast data reading for your Web application.

Tuesday, November 20, 2012

Elmah: filtering "spam" exceptions

Elmah is a great logging facility for ASP.NET.

It can be easily configured in Web.config. Here an example:
 <configuration>  
  <elmah>  
   <errorLog type ="Elmah.XmlFileErrorLog, Elmah" logPath ="~/errors/" />   
   <security allowRemoteAccess ="1" />   
   <errorMail from ="noreply@server.com" to= "admin@example.com" subject ="Web Exception" async= "true "smtpPort ="0"></errorMail>   
  </elmah>  
 </configuration>  

But it's very likely that you will get a lot of "spam" error messages in your log and on your e-mail. So you'll want to filter some of those messages.

You can do it in a very flexible way as follows:
 <configuration>  
  <elmah>  
   <errorLog type ="Elmah.XmlFileErrorLog, Elmah" logPath ="~/errors/" />  
   <errorFilter>  
    <test>  
     <or>  
      <equal binding ="HttpStatusCode" value ="404" type ="Int32" />  
      <regex binding ="Exception.Message" pattern =" ^A potentially dangerous Request$" />  
      <regex binding ="Exception.Message" pattern =" ^The parameters dictionary contains a null entry$" />  
      <and>  
       <regex binding ="Exception.Message "pattern ="^The operation has timed out$" />  
       <regex binding ="Context.Request.ServerVariables['URL']" pattern =".*/some-url/$" caseInsensitive="true" />  
      </and>  
      <and>  
       <regex binding ="Exception.Message" pattern ="^Invalid image profile*" />  
       <regex binding ="Context.Request.ServerVariables['HTTP_USER_AGENT']" pattern ="bot" />  
      </and>  
     </or>  
    </test>  
   </errorFilter>  
   <security allowRemoteAccess ="1" />  
   <errorMail from ="noreply@server.com" to= "admin@example.com" subject ="Web Exception" async= "true "smtpPort ="0"></errorMail>  
  </elmah>  
 </configuration>  

As you can see, we just added <errorFilter> section with various filter conditions, separated by Boolean operations(<or>, <and>). It is a very intuitive way to filter errors that you don't want to track down with Elmah.

Sunday, November 18, 2012

MongoDb for beginners


What is MongoDb?

MongoDb is a non-relational data store for JSON documents. By non-relational we mean that it does not store data in tables like relational databases does. It stores JSON documents.


What is JSON? JSON(JavaScript Object Notation) is a standard for representing data structures in a text-based human-readable form. JSON documents look like this:

{"Name" : "Bob"} 

This very simple JSON document has the key "Name" and the value "Bob". You can create more complex JSON documents with hierarchies:

{"Name" : "Bob", "Age" : 50, "Hobbies" : ["hockey", "football", "movies"], "Account" : {"Login" : "Bobby", "Password" : "12345"}}

JSON documents are stored within MongoDb collections(collections are analogous to tables in a relational database). It’s very useful when writing programs, because this type of data structures looks a lot closer to what you have inside your programs, than relational database does:
 class Person  
 {  
   public string Name;  
   public int Age;  
   public string[] Hobbies;  
   public AccountDetails Account;  
 }  
 class AccountDetails  
 {  
   public string Login;  
   public string Password;  
 }  

That’s new, because you never do that in relational table. The fact that MongoDb stores documents makes programming your domain model very convenient.

Schemaless 

Another interesting aspect about MongoDb is that it also schemaless. Schemaless means that two documents don’t need to have a same schema.

For example, you can store this documents inside the same collection:
{"a" : 1, "b" : 2}
{"a" : 1, "b" : 2, "c" : 3}

MongoDb vs Relational databases


The idea of MongoDb is to retain most of scalability and performance, giving you a lot of functionality to work with, but not quite as much as you can get in relational database management systems. 

That’s because there are few different things are missing in MongoDb:
  • Joins. MongoDb stores documents. Each document is stored in collection. But if you want to do a JOIN between two collections - you can’t do that in MongoDb. And the reason is that JOINs scale very poorly.
  • Transactions. That sound very bad, but the truth is that you don't need transactions in MongoDb in applications where you would need them in relational systems. And the reason is that documents are hierarchical in MongoDb and you can access those documents atomically. 
Choice between non-relational and relational data stores can't be easy. But if you want to create a scalable, high-performance application you should consider MongoDb as an option.

This article is based on video lectures from 10gen education course https://education.10gen.com.