T4 template consuming a WCF service

It’s been a while since I’ve blogged and but I have a valid excuse; I moved to WA state recently and things have been crazy busy. I finally decided to kick myself and do a post so without further ado, the problem at hand:
A co-worker of mine asked me whether its possible to dynamically create a type from some data he is receiving from a WCF service (over HTTP).
My natural response was, why would you need to do that since Visual Studio creates a proxy from the metadata exposed by the service and the return types would typically be DataContracts.
Well, it turns out that instead of returning a strongly typed domain specific object, the service is returning a Dictionary<string,string> where the Key represents an attribute and the Value represents the value of the attribute.

This has obvious problems:

  • Nothing is strongly typed
  • No contract versioning
  • The service could return a variable number of fields
A naive approach is to inspect the data returned by the service and hand code a class with properties based on the type of each key in the Dictionary.
For example, if the Dictionary contained the following KeyValuePairs.
{“Name”,”Jon Smith”}
{“Age”,”20”}
{“Zip”,”90876”}

The class definition would look something like this:
 
  1. public class User  
  2. {  
  3.   public string Name {get;set;}  
  4.   public int Age {get;set;}  
  5.   public int Zip {get;set;}  
  6. }  

That’s fine when you have a couple of KeyValuePairs but what if you had 10 or 20, it gets unwieldy very quickly.
Enter T4 templates, a slick way to generate code for repetitive tasks. I'd never written a T4 template before so I figured this would be a nice excuse to dabble in it a little.

Let’s create a simple service to simulate some data, nothing too fancy

 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Runtime.Serialization;  
  5. using System.ServiceModel;  
  6. using System.Text;  
  7.   
  8. namespace T4WCFService  
  9. {  
  10.     [ServiceContract]  
  11.     public interface IT4WCFService  
  12.     {  
  13.   
  14.         [OperationContract]  
  15.         Dictionary<string,string> GetUser(string userID);         
  16.     }  
  17. }  
and its implementation...
 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Runtime.Serialization;  
  5. using System.ServiceModel;  
  6. using System.Text;  
  7.   
  8. namespace T4WCFService  
  9. {  
  10.     public class T4Service : IT4WCFService  
  11.     {  
  12.  
  13.         #region IT4WCFService Members  
  14.   
  15.         public Dictionary<stringstring> GetUser(string userID)  
  16.         {  
  17.             if (userID == "jsmith")  
  18.             {  
  19.                 return new Dictionary<stringstring>   
  20.                         {   
  21.                             { "Name""Jack smith" },  
  22.                             { "Age""30" },   
  23.                             { "City""San francisco" },  
  24.                             { "State""CA"  },   
  25.                             { "Zip""94061"  },  
  26.                             { "Country""USA"  }   
  27.   
  28.   
  29.                         };    
  30.             }  
  31.             if (userID == "jasmith")  
  32.             {  
  33.                 return new Dictionary<stringstring>   
  34.                         {   
  35.                             { "Name""Jane smith" },  
  36.                             { "Age""28" },   
  37.                             { "City""Portland" },  
  38.                             { "State""OR"  },   
  39.                             { "Zip""98685"  },  
  40.                             { "Country""USA"  }   
  41.                         };  
  42.             }  
  43.             return new Dictionary<stringstring>();              
  44.         }  
  45.  
  46.         #endregion  
  47.     }  
  48. }  

The service just simulates returning some dummy users based on a userID and returns an empty Dictionary if no matching user is found, and it’s exposed using
WSHttpBinding

The <system.servicemodel> looks as follows:
 
  1. <system.serviceModel>  
  2.   <services>  
  3.     <service behaviorConfiguration="T4WCFService.Service1Behavior"  
  4.       name="T4WCFService.T4Service">  
  5.       <endpoint address="WsHttpT4Service" binding="wsHttpBinding" name="WsHttpT4Service"  
  6.         contract="T4WCFService.IT4WCFService">  
  7.         <identity>  
  8.           <dns value="localhost" />  
  9.         </identity>  
  10.       </endpoint>  
  11.       <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />  
  12.       <endpoint address="basicHttpTService" binding="basicHttpBinding"  
  13.         name="basicHttpTService" contract="T4WCFService.IT4WCFService" />  
  14.       <host>  
  15.         <baseAddresses>  
  16.           <add baseAddress="http://WCFServices" />  
  17.         </baseAddresses>  
  18.       </host>  
  19.     </service>  
  20.   </services>  
  21.   <behaviors>  
  22.     <serviceBehaviors>  
  23.       <behavior name="T4WCFService.Service1Behavior">  
  24.         <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->  
  25.         <serviceMetadata httpGetEnabled="true"/>  
  26.         <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->  
  27.         <serviceDebug includeExceptionDetailInFaults="false"/>  
  28.       </behavior>  
  29.     </serviceBehaviors>  
  30.   </behaviors>  
  31. </system.serviceModel>  

If you(like me) have never created a T4 template before, I’d strongly suggest reading this article first.

Welcome back, now that you know how to create a simple T4 template, let’s get started.
T4 enables writing reusable modules that can be consumed from other T4 modules. For the purpose of this exercise I decided to create a template which encapsulates invoking a WCF service and returning the result back to the caller.

Create a new Console Application and add a service reference to the service we created above, also add a new T4 file to your project called WCFServiceInvoker.tt

T4_WCFServiceInvoker

Double click on WCFServiceInvoker.tt and the file should open up in markup mode.Delete the default code in the .tt file and add the following code:

 
  1. <#@ template language="C#v3.5"#>  
  2. <#@ output extension=".cs"#>   
  3. <#@ assembly name ="System.ServiceModel" #>   
  4. <#@ import namespace="System.Collections.Generic"#>  
  5. <#@ import namespace="System.Reflection"#>  
  6. <#@ import namespace="System.ServiceModel.Channels"#>  
  7. <#@ import namespace="System.ServiceModel"#>  
  8.   
  9. <#+  
  10.     public class WCFServiceInvoker<TInterfaceType,TReturnType> where TReturnType:class  
  11.     {  
  12.       public string EndPointAddress {get;set;}  
  13.       public string EndPointName {get;set;}  
  14.       public Type ServiceInterfaceType {get;set;}        
  15.       public Binding Binding {get;set;}  
  16.       public string MethodName {get;set;}  
  17.       public object[] Parameters {get;set;}  
  18.       public TReturnType InvokeMethod()  
  19.       {  
  20.             EndpointAddress endpoint = new EndpointAddress(EndPointAddress);  
  21.             Type typeDef = typeof(ChannelFactory<>).MakeGenericType(typeof(TInterfaceType));  
  22.             var typeInst = Activator.CreateInstance(typeDef,new object[]{Binding,endpoint});  
  23.             var channel = typeInst.GetType().InvokeMember("CreateChannel", BindingFlags.InvokeMethod,null, typeInst, null);  
  24.             var results = channel.GetType().InvokeMember(MethodName, BindingFlags.InvokeMethod, null,channel, Parameters);  
  25.             return results as TReturnType;  
  26.       }  
  27.         
  28.     }  
  29. #>  

There is a lot going on here.

  • The template and output directives indicate that the code is written in C# and the generated file needs to be have an extension of .cs.
  • The <#@assembly> directive is similar to an “Add Reference” in Visual Studio, it allows for referencing external assemblies.
  • The <#@import> directive is similar to a “using” statement, in that it brings the types in the specified namespace in scope so that the template can avail of them.
  • The <#+ #> directive is called Class feature block and it allows for writing class definitions within the template.
    This allows for encapsulating reusable logic.
    NOTE: The class definitions in this block are not emitted out to the final .cs file.
  • The WCFServiceInvoker class contains a bunch of properties, whose values(when set) are used for invoking a specified service dynamically.
  • The type parameters “TInterfaceType” represents the type of the interface on which the method specified in the "MethodName" parameter will be invoked.
  • The type parameter “TReturnType” represents the type of the result returned from the method call.

Using “TInterfaceType” we dynamically create a type definition for ChannelFactory<T> using reflection, and then create an instance of it, on which we then call CreateChannel which in turns returns us an instance of a type which implements TInterfaceType. Once we have a “TInterfaceType” instance we then go ahead and invoke the specified “MethodName” with the parameters specified in the “Parameters” object[] property and get the result back which is typed to “TReturnType” and returned to the caller.

Phew! that’s a mouthful and we are not done yet. For now just keep in mind that this template is merely a helper which encapsulates the details on dynamically invoking a WCF service in a strongly typed manner.

Now onto the main task of writing a template to solve our problem.

Add another T4 template to the project and call it UserClass.tt
T4_UserClass

As before delete the code from the .tt file and add the following:

 
  1. <#@ assembly name ="System.ServiceModel" #>   
  2. <#@ assembly name ="T4WCFService.dll" #>   
  3. <#@ assembly name ="System.ServiceModel" #>   
  4. <#@ import namespace="System.Collections.Generic"#>  
  5. <#@ import namespace="System.Reflection"#>  
  6. <#@ import namespace="System.ServiceModel.Channels"#>  
  7. <#@ import namespace="System.ServiceModel"#>  
  8. <#@ import namespace="T4WCFService"#>  
  9. <#@ include file="WCFServiceInvoker.tt" #>  
  10. using System.Collections.Generic;  
  11. namespace T4ClassFromDict  
  12. {  
  13.     public class User  
  14.     {  
  15.         <#  
  16.         WCFServiceInvoker<IT4WCFService,Dictionary<string,string>> invoker = new WCFServiceInvoker<IT4WCFService,Dictionary<string,string>>();  
  17.         invoker.EndPointAddress = "http://localhost:24551/Service1.svc/WsHttpT4Service";  
  18.         invoker.EndPointName = "WsHttpT4Service";  
  19.         invoker.ServiceInterfaceType = typeof(IT4WCFService);  
  20.         invoker.Binding = new WSHttpBinding();  
  21.         invoker.MethodName = "GetUser";  
  22.         invoker.Parameters = new object[]{"jsmith"};      
  23.         Dictionary<string,string> result = invoker.InvokeMethod();  
  24.         #>  
  25.          <#foreach(KeyValuePair<string,string> item in result){  
  26.          #>  
  27.            
  28.          public <#= item.Key.GetType().Name.ToLower()#> <#=item.Key#>  
  29.          {  
  30.              get;         
  31.              set;  
  32.          }  
  33.          <#}#>  
  34.            
  35.          public static User GetUser(Dictionary<string,string> dict)  
  36.          {  
  37.              var user = new User();  
  38.              foreach(KeyValuePair<string,string> kvp in dict)  
  39.              {  
  40.                 typeof(User).GetProperty(kvp.Key).SetValue(user,kvp.Value,null);                  
  41.              }  
  42.              return user;  
  43.          }  
  44.     }  
  45. }  

We've included the template file we created before so that we can reuse it to invoke any WCF Service.
We then proceed to create an instance of WCFServiceInvoker and set it's properties to invoke the WCF service we've created.
The result of "invoker.InvokeMethod()" is a Dictionary<string,string> which we then loop through creating public properties.

We use the type of the Key as the type of the property and the Key itself as the property name.

We've also created the definition of factory method which accepts a Dictionary<string,string> and returns a User object.

Note that we've added a direct reference to the service assembly in this template so that we can get a reference to IT4WCFService.
This is just to keep the example simple, ideally you would want to seperate the interface and implementation assemblies and have a reference to just the interface assembly.

T4 templates are executed typically when saved or by right clicking on the .tt file and selecting "Run Custom Tool".
Before running the template, ensure that the WCF service is up and running.

On running/saving the template, the following class definition is generated.

 
  1. using System.Collections.Generic;  
  2. namespace T4ClassFromDict  
  3. {  
  4.     public class User  
  5.     {  
  6.                            
  7.          public string Name  
  8.          {  
  9.              get;         
  10.              set;  
  11.          }  
  12.                    
  13.          public string Age  
  14.          {  
  15.              get;         
  16.              set;  
  17.          }  
  18.                    
  19.          public string City  
  20.          {  
  21.              get;         
  22.              set;  
  23.          }  
  24.                    
  25.          public string State  
  26.          {  
  27.              get;         
  28.              set;  
  29.          }  
  30.                    
  31.          public string Zip  
  32.          {  
  33.              get;         
  34.              set;  
  35.          }  
  36.                    
  37.          public string Country  
  38.          {  
  39.              get;         
  40.              set;  
  41.          }  
  42.                    
  43.          public static User GetUser(Dictionary<string,string> dict)  
  44.          {  
  45.              var user = new User();  
  46.              foreach(KeyValuePair<string,string> kvp in dict)  
  47.              {  
  48.                 typeof(User).GetProperty(kvp.Key).SetValue(user,kvp.Value,null);                  
  49.              }  
  50.              return user;  
  51.          }  
  52.     }  
  53. }  

A client can then use the generates class as follows:

 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net;  
  6. using System.IO;  
  7. using System.ServiceModel;  
  8. using T4WCFService;  
  9. using System.Reflection;  
  10.   
  11.   
  12. namespace T4ClassFromDict  
  13. {    
  14.   
  15.     class Program  
  16.     {  
  17.   
  18.         public string Foo { getset; }  
  19.         static void Main(string[] args)  
  20.         {            
  21.             var client = new T4Service.T4WCFServiceClient("WsHttpT4Service");  
  22.             var data = User.GetUser(client.GetUser("jsmith"));  
  23.         }  
  24.     }  
  25. }  

NOTE: The console app hosting the project has a direct project reference to WCF service project since it needs the IT4WCFService definition. and since T4 engine is running inside Visual studio it locks the assembly, so rebuilding the WCF service after template generation does not work.
As mentioned previously the solution to this is to have seperate assemblies for the interface and service implementation.
Download Code

Why no Anonymous Iterators in C#

Yes I’m a language geek and yes the awesome  Eric Lippert is my idol when it comes to anything C# and the CLR, I’ve been following his blog for a long time and recently Eric wrote an awesome series on the how and why of Iterator Blocks. The entire series is very well worth a read, but then again I’d read almost anything Eric writes from why the sky is blue to why the Falkirk Wheel has horns.

I had posed a question on this post about why there are no anonymous iterators in C#. Eric provided a very good answer to that comment and I was highly flattered when he did a follow up post on this very question here.

Thanks Eric!

Creating Higher Level APIs with TPL

The BCL has a bunch of APIs which provide asynchronous versions of operations in the form of either Beginxxx/Endxxx or XyzCompleted, the former known as Asynchronous Programming Model(APM) and the latter known as Event Based Asynchronous Pattern (EAP). TPL provides a nice abstraction for performing asynchronous operations as Tasks using delegates, but what can you do for working with these existing BCL classes which already have an async version?

Here is an example.
Let's say we need to download some data from the web and save it to a file, you would typically use the WebClient class and write something like this today (wrapped in a method of course)
  1. WebClient client = new WebClient();  
  2.            client.DownloadDataAsync(new Uri("http://www.bing.com"));  
  3.            client.DownloadDataCompleted += new DownloadDataCompletedEventHandler((s, e) =>  
  4.            {  
  5.                if (e.Error != null)  
  6.                {  
  7.                    throw e.Error;  
  8.                }  
  9.                if (!e.Cancelled)  
  10.                {  
  11.                    using (FileStream fs = new FileStream("bing.htm", FileMode.CreateNew))  
  12.                    {  
  13.                        fs.Write(e.Result,0,e.Result.Length);  
  14.                        fs.Flush();  
  15.                        fs.Close();  
  16.                    }  
  17.                }  
  18.            }  
  19.            );  
  20.            Console.Read();  

Yuck not very pretty is it! It's kinda smelly and looking at the code, it doesn't really capture the essense of what we are trying to do, besides if the client were to call a method which does this work, we'd have to ensure that the client thread blocks till the continuation completes or conversely provide a mechanism such as a WaitHandle that the client can wait on, not very expressive is it?


Let's see how we can achieve the same results using the Task API.
 
  1. private static TaskCompletionSource<byte[]> CreateSource(object state)  
  2. {  
  3.     return new TaskCompletionSource<byte[]>(state);  
  4. }  
  5.   
  6. private static void SetCompletionSource<T>(  
  7.     TaskCompletionSource<T> tcs,  
  8.     AsyncCompletedEventArgs e,  
  9.     Func<T> getResult)  
  10. {  
  11.     if (e.UserState == tcs)  
  12.     {  
  13.         if (e.Cancelled)  
  14.             tcs.TrySetCanceled();  
  15.         else  
  16.             if (e.Error != null) tcs.TrySetException(e.Error);  
  17.         else  
  18.             tcs.TrySetResult(getResult());  
  19.     }  
  20. }  
  21.   
  22. public static Task<byte[]> DownloadBytesTask(this WebClient webClient, string uri)  
  23. {  
  24.     var source = CreateSource(uri);  
  25.     DownloadDataCompletedEventHandler handler = null;  
  26.     handler = (object s, DownloadDataCompletedEventArgs e) =>  
  27.     {  
  28.         SetCompletionSource(source, e, () => e.Result);  
  29.         webClient.DownloadDataCompleted -= handler;  
  30.     };  
  31.     webClient.DownloadDataAsync(new Uri(uri), source);  
  32.     webClient.DownloadDataCompleted += handler;  
  33.     return source.Task;  
  34. }  

We've wrapped up the async network operation into a Task as an extension method.
Let's dig in a little...

In DownloadBytesTask, we first create a TaskCompletionSource which provides a mechanism to create a Task to hand out to consumers such that the only legal state modification to the Task can be performed via the methods available on the TaskCompletionSource itself and not on the instance of the Task directly, this is precisely the behavior needed for a Task that is downloading content from the web asynchronously;it doesn't make sense for the client to explicitly start such a Task which has already started downloading data and such an operation should really be considered illegal, TaskCompletionSource enables this behavior.

In the callback we call SetCompletionSource which is responsible for transitioning the state of the Task based on the results of the asynchronous operation such as whether it errored out, or completed or whether it was cancelled.

We then proceed to start the asynchronous download by calling DownloadDataAsync method of the WebClient instance.

Couple of things to note:

  • The callback has been unhooked from the event in the callback to ensure that we don't have a memory leak.
  • The Task has already started since "DownloadDataAsync" has already been invoked, and it is this started Task that we return from the method.
The client can now perform the asynchronous download and saving of content like so:
 
  1. public class Program  
  2. {  
  3.         public static Task WriteToFileTask(string fileName, byte[] bytes)  
  4.         {  
  5.             FileStream fs = new FileStream(fileName, FileMode.CreateNew);  
  6.             var task = Task.Factory.FromAsync(fs.BeginWrite, fs.EndWrite, bytes, 0, bytes.Length, null);  
  7.             return task;  
  8.         }  
  9.   
  10.         static void Main(string[] args)  
  11.         {  
  12.             WebClient wc = new WebClient();  
  13.             var task = wc.DownloadBytesTask("http://www.bing.com/");                                     
  14.             var continuationTask = task.ContinueWith(a => WriteToFileTask("bing.htm", a.Result));  
  15.             continuationTask.Wait();              
  16.         }  
  17. }  

The DownloadBytes extension method on the WebClient returns a Task which has already started, we then specify a continuation to execute "after" the Task completes by calling the "ContinueWith" method on the Task instance which in this case is itself a Task which works on the result of the antecedent task (a byte[]) obtained by calling the "WriteToFileTask" method which is responsible for writing out the byte[] to a file.

It's important to note that we have to wait for the "continuation" to complete by calling continuationTask.Wait(), otherwise the process will terminate since we are running on a console app. The same would hold true in case of a Webforms client since the calling Page would continue processing and not wait for the Task to complete.

Notice how the client code seems pretty terse in terms of expressing the intent. One can easily read the code and figure out what's going on.
As always happy coding!

CLR via C# 3rd Edition

Some book news…Jeff Richter is one of my favorite authors and I’ll read just about anything he writes. His last book CLR via C#, 2nd Edition left me wanting more, luckily Jeff has signed into a contract for writing a 3rd edition of the book updated for C#3.0/4.0 and .NET 4.0

Retrieving Added Entities from the ObjectStateManager to avoid duplication

Let's say we neede to process a bunch of entities coming from an XML file, create EDM entites for each XML element and eventually persist them. Very trivial to accomplish using a little bit of LINQ.

  1. <Roles>  
  2.   <Role name="Admin"/>  
  3.   <Role name="Reader"/>  
  4.   <Role name="Writer"/>    
  5. </Roles>  

  1. var doc = XDocument.Load("Roles.xml");  
  2. var roles = doc.Element("Roles").Elements("Role").Select(x => new Role { RoleName = (string)x.Attribute("name") });  
  3. PermissionsAPIContext context = new PermissionsAPIContext();  
  4.   
  5. foreach (var role in roles)  
  6. {  
  7.   context.AddToRoleSet(role);  
  8. }  
  9. context.Savechanges()  
But wait, let's make this a little interesting...

  1. <Roles>  
  2.   <Role name="Admin"/>  
  3.   <Role name="Reader"/>  
  4.   <Role name="Writer"/>  
  5.   <Role name="Reader"/>  
  6. </Roles>  
See the problem now? If we process the above XML using the code from before, we end up adding the same entity twice!
So what do we do now?
ObjectStateManager to the rescue, let's rewrite the piece of code as follows:

  1. var doc = XDocument.Load("Roles.xml");  
  2. var roles = doc.Element("Roles").Elements("Role").Select(x => (string)x.Attribute("name"));  
  3. PermissionsAPIContext context = new PermissionsAPIContext();  
  4. foreach (var role in roles)  
  5. {  
  6.    Role roleEntity = GetRole(role, context);  
  7.    if (roleEntity.EntityState == EntityState.Added || roleEntity.EntityState == EntityState.Detached)  
  8.    {  
  9.       context.AddToRoleSet(roleEntity);  
  10.    }                  
  11.  }  
  12. context.SaveChanges();  
  13.   
  14.   
  15. private static Role GetRole(string roleName,PermissionsAPIContext context)  
  16. {  
  17.   //NOTE: we could have used string.Compare(r.RoleName,roleName,true) == 0 inside the body of the lambda as a cleaner   
  18.   //way to do this but this translates to some pretty snarly and inefficient SQL!  
  19.     var roleEntity = context.RoleSet.FirstOrDefault(r => r.RoleName.Trim().ToLower() == roleName.Trim().ToLower());  
  20.     if (roleEntity == null)  
  21.      {  
  22.            var stateEntries = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EtityState.Modified | EntityState.Unchanged);  
  23.            var roleEntityEntries = stateEntries.Select(s => s.Entity).OfType<Role>();  
  24.            roleEntity = roleEntityEntries.FirstOrDefault(r => r.RoleName.Trim().ToLower() == roleName.Trim().ToLower());  
  25.            if (roleEntity == null)  
  26.            {  
  27.                return new Role { RoleName = roleName };  
  28.            }  
  29.      }  
  30.      return roleEntity;  
  31. }  
A few of things note worthy here
1) In GetRoles() we first query the ObjectContext to check whether there is already a role present with the given name, if so we 
    simply return a reference to the existing entity instance
2) If the role is not existing then we check to see whether a role with the given name was added to the context, if so then we just
    get a handle to this previously added(but not yet persisted) role and return that.
3) If the role is not existing and was not added previously then we create a new Role entity and return.
4) The caller checks whether the returned entity is an existing one and if not it's added to the ObjectContext.

After we are done processing all entities, we save all entities and we are done.

The above mechanism allows us to safely sidestep duplicates while processing based on some equality rule(which in this case happens to be the role name).

Hope this helps.

Inside TPL video

No code today. Instead, here is a link to a great video from Channel9 I found, which takes a deep dive into the underlying mechanics of how TPL does what it does and some of the enhancements that the thread pool has undergone.  Albeit a year old, this video goes into details of the work stealing algorithm and local thread queues that helps increase throughput.

From the perspective of being a consumer of TPL, you can be blissfully ignorant of what happens behind the scenes, but understanding the mechanics and some of the design decisions that the team made can help gain a deeper appreciation of TPL which ultimately can help write more thoughtful code.

I was impressed by the clarity in which the concepts were presented and explained.  Plan on setting aside about an hour to watch this video, but every minute is time well spent!

Performing multiple Asynchronous Actions using TPL

I finally had a chance to install VS2010 Beta 1.Full instruction on how to here
VS2010 has undergone a major overhaul since VS 2008, a peek are some of the cool new eye candy can be found here
I've been waiting to get my hands on the TPL/PLINQ stuff and the Beta was definitely worth the wait. In a previous post we talked about using asynchronous actions for performing long running operations.

I was anxious to see how the new TPL stuff would help in achieving the same thing.

Interestingly enough, the TPL API is based on Actions as well, allowing both the generic and non-generic versions to be used for creating a Task(also supports Funcs).

The Thread pool has undergone some major rework, especially the scheduling algorithm is much more smarter now than the current implementation in.NET 3.5

The unit of abstraction is a Task as opposed to a Thread, so let's dive in and see how this looks and feels as opposed to the abstraction we previously built for asynchronous Actions. In the simplest form, the equivalent declaration for creating a Task that can execute an Action asynchronously looks like so:

 

 
  1.  public static void SomeMethod()  
  2.  {  
  3.   
  4.      // do something here....  
  5.      Console.WriteLine("In some method");  
  6.   
  7.  }   
  8.   
  9. static void Main(string[] args)  
  10. {  
  11.     var task = Task.Factory.StartNew(SomeMethod);  
  12.    task.Wait();  
  13.  }  

You start a task and Wait for it to complete. Lets create a bunch of these tasks to execute on the GetUsers(), GetCountries() and GetLanguages() method from the previous post.

 

 
  1. Task[] tasks = new Task[]  
  2. {  
  3.    Task.Factory.StartNew(() => countries = GetCountries()),  
  4.    Task.Factory.StartNew(() => countries = GetUsers()),  
  5.    Task.Factory.StartNew(() => countries = GetLanguages())  
  6. };  
  7. Task.WaitAll(tasks);  

This looks fairly similar from a usage persepctive to what we had for executing asynchronous actions

 
  1. List<Action> actions = new List<Action>()  
  2. {  
  3.     () => countries = GetCountries(),  
  4.     () => users = GetUsers(),  
  5.     () => languages = GetLanguages(),  
  6. };          
  7. actions.ExecAsync();  

One obviously noticeable difference in using the Task is that you use the Factory method StartNew to create and execute the task at the point of declaration, and what you get back is a handle to the executing Task. So the Task[] contains a handle to all the executing tasks.
The ExecAsync extension method on the other hand is passed a collection of Actions to execute. I find the idea of being able to create and execute the Task in one statement very useful and terse.

Let's now compare the performance of executing Actions using Tasks v/s executing Actions using The ExecAsync()

 

 
  1. public static class Extensions  
  2.    {  
  3.        public static void ExecAsync(this IEnumerable<Action> actions)  
  4.        {  
  5.            int count = 0;  
  6.            AutoResetEvent[] events = new AutoResetEvent[actions.Count()];  
  7.            IAsyncResult[] results = new IAsyncResult[actions.Count()];  
  8.            for (int i = 0; i < events.Length; i++)  
  9.            {  
  10.                events[i] = new AutoResetEvent(false);  
  11.            }  
  12.   
  13.            foreach (var action in actions)  
  14.            {  
  15.                int localCount = count;  
  16.                results[count++] =  
  17.                    action.BeginInvoke((r) =>  
  18.                    {  
  19.                        try  
  20.                        {  
  21.                            if (r.IsCompleted)  
  22.                            {  
  23.                                Action act = r.AsyncState as Action;  
  24.                                act.EndInvoke(results[localCount]);  
  25.                            }  
  26.                        }  
  27.                        finally  
  28.                        {  
  29.                            //set the event regardless of whether there is an exception so that the main thread  
  30.                            //is not blocked indefinitely.  
  31.                            events[localCount].Set();  
  32.                        }  
  33.                    }, action);  
  34.            }  
  35.            WaitHandle.WaitAll(events);  
  36.        }  
  37.    }  
  38.   
  39.    public class Program  
  40.    {  
  41.        public static string[] GetUsers()  
  42.        {  
  43.            //simulate a long running operation  
  44.            Thread.SpinWait(3000);  
  45.            Console.WriteLine("Current Thread:{0}", Thread.CurrentThread.ManagedThreadId);  
  46.            return new[] { "Jack""Jon""Jim" };  
  47.        }  
  48.   
  49.        public static string[] GetCountries()  
  50.        {  
  51.            //simulate a long running operation  
  52.            Thread.SpinWait(3000);  
  53.            Console.WriteLine("Current Thread:{0}", Thread.CurrentThread.ManagedThreadId);  
  54.            return new[] { "US""UK""Canada" };  
  55.        }  
  56.   
  57.        public static string[] GetLanguages()  
  58.        {  
  59.            //simulate a long running operation  
  60.            Thread.SpinWait(3000);  
  61.            Console.WriteLine("Current Thread:{0}", Thread.CurrentThread.ManagedThreadId);  
  62.            return new[] { "English""French""German" };  
  63.        }  
  64.        static void Main(string[] args)  
  65.        {  
  66.   
  67.            string[] countries;  
  68.            string[] users;  
  69.            string[] languages;  
  70.            List<Action> actions = new List<Action>()  
  71.            {  
  72.                () => countries = GetCountries(),  
  73.                () => users = GetUsers(),  
  74.                () => languages = GetLanguages(),  
  75.            };  
  76.            Console.WriteLine("Running Actions Asynchronously");  
  77.            Console.WriteLine("----------------------");  
  78.            Stopwatch watch = Stopwatch.StartNew();  
  79.            actions.ExecAsync();  
  80.            watch.Stop();  
  81.            Console.WriteLine("Total time taken:{0} milliseconds", watch.ElapsedMilliseconds);  
  82.   
  83.            Console.WriteLine();  
  84.            Console.WriteLine("Running Actions using Tasks");  
  85.            Console.WriteLine("----------------------");  
  86.            watch.Reset();  
  87.            watch.Start();  
  88.            Task[] tasks = new Task[]  
  89.            {  
  90.               Task.Factory.StartNew(() => countries = GetCountries()),  
  91.               Task.Factory.StartNew(() => countries = GetUsers()),  
  92.               Task.Factory.StartNew(() => countries = GetLanguages())  
  93.            };  
  94.            Task.WaitAll(tasks);  
  95.            watch.Stop();  
  96.            Console.WriteLine("Total time taken:{0} milliseconds", watch.ElapsedMilliseconds);  
  97.        }  
  98.    }  

Let's give it a spin and see the numbers:

The version using Tasks is almost 5 times faster! which suggests that TPL is doing a far superior job under the covers in effectively scheduling and executing the Actions.
TPL has a host of goodness which I've barely started exploring.Among other goodies, is the ability to have parent-child relationships between tasks and support for cancellation using a CancellationToken.
I hope to do more frequent posts especially around TPL since this has piqued my interest.
As always happy coding!

kick it on DotNetKicks.com

Using multiple Object Contexts in a Transaction

The scenario: You have 2 Entity Models, and you need to call operations on the ObjectContext of each of them, the operations should be atomic, in that either both operations should succeed or fail so that your databases are consistent.
This is fairly straightforward to accomplish using a TransactionScope.
ObjectServices is smart enough to detect if the ObjectContext is in a surrounding TransactionScope and if so,use that scope.
NOTE:If a scope is not specified, then ObjectContext by default creates a new scope internally when saving changes.

 
  1. using (TransactionScope scope = new TransactionScope())  
  2.            {  
  3.                using (RequestDBContext context = new RequestDBContext())  
  4.                {  
  5.                    RequestType rt = new RequestType  
  6.                    {  
  7.                         Name="Test-2",                            
  8.                    };  
  9.                    context.AddToRequestTypeSet(rt);  
  10.                    context.SaveChanges();  
  11.                }  
  12.   
  13.                using (RequestDBContext context = new RequestDBContext())  
  14.                {  
  15.                      
  16.                    Status stat = context.StatusSet.First(s => s.Name == "Pending Approval");  
  17.                    context.DeleteObject(stat);  
  18.                    context.SaveChanges();  
  19.                }  
  20.                scope.Complete();  
  21.            }  

In the above code I'm using the same EDM for both ObjectContexts, but I could very well use different EDMs.
If we reach the end of the 2nd using statement, then we can complete the transaction and persist all our changes.
If an exception is thrown then nothing is changed in the database and the transaction aborts.
Hope this helps.


UPDATE:5/16/09
Using TransactionScope requires MSDTC, the following links have good information to help setup/troubleshoot MSDTC for various environments
How to Enable MSDTC on a Web Server
New functionality in the Distributed Transaction Coordinator service in Windows Server 2003 Service Pack 1 and in Windows XP Service Pack 2
Thursday, February 19, 2009 5:08 PM mmazur How to configure and troubleshoot MSDTC

kick it on DotNetKicks.com

Handling WorkflowRuntime events for IIS hosted WCF + WF services

The WorkflowRuntime class has a host of interesting methods and useful events. Events such as Completed, Perssited, Idled are invaluable when debugging and in understanding how a workflow instance is behaving.
These events are easily accessible when self hosting the runtime since you can just hook up event handlers for these events and react to these events as you see fit.
But, when the workflow runtime is hosted in IIS/WAS/Cassini host, you don’t have a direct handle to the runtime for hooking up these events.
The .svc file for the WCF service contains the WorkflowServiceHostFactory that WCF uses for servicing workflow service requests.

 
  1. <%@ ServiceHost Language="C#"   
  2. Debug="true"   
  3. Service="RequestWFServiceLib.ApprovalWorkflow"  
  4. Factory="System.ServiceModel.Activation.WorkflowServiceHostFactory"%>  

We can easily subclass WorkflowServiceHostFactory and replace the Factory attribute in the .svc file with a custom implementation of this class where in we override the CreateServiceHost Method and get a handle to the WorkflowRuntime and hook up the event handlers we need.

 
  1.    public class CustomWorkflowServiceHost : WorkflowServiceHostFactory  
  2. {  
  3.   
  4.        public override System.ServiceModel.ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)  
  5.        {  
  6.            ServiceHostBase hostBase = base.CreateServiceHost(constructorString, baseAddresses);  
  7.            WorkflowRuntimeBehavior runtimeBehavior = hostBase.Description.Behaviors.Find<WorkflowRuntimeBehavior>();  
  8.            WorkflowRuntime runtime = runtimeBehavior.WorkflowRuntime;  
  9.            runtime.WorkflowIdled += runtime_WorkflowIdled;  
  10.            runtime.Started += runtime_Started;  
  11.            runtime.Stopped += runtime_Stopped;  
  12.            runtime.WorkflowStarted += runtime_WorkflowStarted;  
  13.            runtime.WorkflowSuspended += runtime_WorkflowSuspended;  
  14.            runtime.WorkflowUnloaded += runtime_WorkflowUnloaded;  
  15.            runtime.WorkflowCreated += runtime_WorkflowCreated;  
  16.            runtime.WorkflowTerminated += runtime_WorkflowTerminated;  
  17.            runtime.WorkflowResumed += runtime_WorkflowResumed;  
  18.            runtime.WorkflowPersisted += runtime_WorkflowPersisted;  
  19.            runtime.WorkflowLoaded += runtime_WorkflowLoaded;  
  20.            runtime.WorkflowCompleted += runtime_WorkflowCompleted;  
  21.            runtime.WorkflowAborted += runtime_WorkflowAborted;  
  22.            return hostBase;  
  23.   
  24.        }  
  25.   
  26.        void runtime_WorkflowAborted(object sender, WorkflowEventArgs e)  
  27.        {  
  28.            Debug.WriteLine(string.Format("WorkflowInstance {0} Aborted", e.WorkflowInstance.InstanceId.ToString()));  
  29.        }  
  30.   
  31.        void runtime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)  
  32.        {  
  33.            Debug.WriteLine(string.Format("WorkflowInstance {0} Completed", e.WorkflowInstance.InstanceId.ToString()));  
  34.        }  
  35.   
  36.        void runtime_WorkflowLoaded(object sender, WorkflowEventArgs e)  
  37.        {  
  38.            Debug.WriteLine(string.Format("WorkflowInstance {0} Loaded", e.WorkflowInstance.InstanceId.ToString()));  
  39.        }  
  40.   
  41.        void runtime_WorkflowPersisted(object sender, WorkflowEventArgs e)  
  42.        {  
  43.            Debug.WriteLine(string.Format("WorkflowInstance {0} Persisted", e.WorkflowInstance.InstanceId.ToString()));  
  44.        }  
  45.   
  46.        void runtime_WorkflowResumed(object sender, WorkflowEventArgs e)  
  47.        {  
  48.            Debug.WriteLine(string.Format("WorkflowInstance {0} Resumed", e.WorkflowInstance.InstanceId.ToString()));  
  49.        }  
  50.   
  51.        void runtime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)  
  52.        {  
  53.            Debug.WriteLine(string.Format("WorkflowInstance {0} Terminated", e.WorkflowInstance.InstanceId.ToString()));  
  54.        }  
  55.   
  56.        void runtime_WorkflowCreated(object sender, WorkflowEventArgs e)  
  57.        {  
  58.            Debug.WriteLine(string.Format("WorkflowInstance {0} Created", e.WorkflowInstance.InstanceId.ToString()));  
  59.        }  
  60.   
  61.        void runtime_WorkflowUnloaded(object sender, WorkflowEventArgs e)  
  62.        {  
  63.            Debug.WriteLine(string.Format("WorkflowInstance {0} Unloaded", e.WorkflowInstance.InstanceId.ToString()));  
  64.        }  
  65.   
  66.        void runtime_WorkflowSuspended(object sender, WorkflowSuspendedEventArgs e)  
  67.        {  
  68.            Debug.WriteLine(string.Format("WorkflowInstance {0} Suspended", e.WorkflowInstance.InstanceId.ToString()));  
  69.        }  
  70.   
  71.        void runtime_WorkflowStarted(object sender, WorkflowEventArgs e)  
  72.        {  
  73.            Debug.WriteLine(string.Format("WorkflowInstance {0} Started", e.WorkflowInstance.InstanceId.ToString()));  
  74.        }  
  75.   
  76.        void runtime_Stopped(object sender, WorkflowRuntimeEventArgs e)  
  77.        {  
  78.            Debug.WriteLine("Workflow runtime Stopped");  
  79.        }  
  80.   
  81.        void runtime_Started(object sender, WorkflowRuntimeEventArgs e)  
  82.        {  
  83.            Debug.WriteLine("Workflow runtime Started");  
  84.        }  
  85.   
  86.        void runtime_WorkflowIdled(object sender, WorkflowEventArgs e)  
  87.        {  
  88.            Debug.WriteLine("Workflow runtime Idled");  
  89.        }  
  90. }  

the .svc file is updated to include the name of our custom implementation. That’s all there is to it.

 
  1. <%@ ServiceHost Language="C#"   
  2. Debug="true"   
  3. Service="RequestWFServiceLib.ApprovalWorkflow"  
  4. Factory="RequestWFServiceLib.CustomWorkflowServiceHost"%>  

kick it on DotNetKicks.com

ASP.NET Caching

I needed a quick way to cache some data for a feature I’m currently working on. The scenario is that the user should be able to type ahead and be presented with a list of matching options (AJAX auto complete). This data is coming from an external web service and is exposed via the core API of the application which in turn is exposed over WCF. So for AJAX to be able to get to this data it must talk to the WCF service, but this is not directly possible since cross site scripting is not allowed in the browser(at least not directly). So for AJAX to be able to consume this data I had to create a proxy WCF service implemented in the same project as the web application which in turn invokes the core WCF service to return this data.

Hence the proxy WCF service acts as an intermediary to fetch the data for auto complete. Now, the data is fairly static for the most part and might change every now and then. Moreover the data set is arguably large(approx 1000 items), so we now have 3 service layers (1 for the proxy WCF service, one for the core API WCF service and one for the external service which provides the actual data) to navigate through before the data is sent to the browser, clearly this is a performance bottleneck since I can’t afford to have this chatty behavior every single time a user types something in.

This leads us to caching the data, I could cache the data either in the core API object which invokes the remote service, OR in the core WCF service OR in the proxy WCF service.

Each has its own caveats. If I cache in the core API object or in the core WCF service I would need to either implement a custom caching mechanism or use an out of the box caching API such as the Enterprise Library Caching Application Block, I would also need to implement a expiration policy to ensure that the cache is flushed periodically, this would help provide some performance boost but there is still the overhead involved in marshalling this data to the client itself on every call.

If I cache at the client side (ASP.NET) then I can use the ASP.NET Cache object out of the box, and set up a time/file based dependency to periodically purge the cache, the downside is that when other clients invoke the core WCF service then the core API will invoke the external service every single time, and we could end up swamping both, the core WCF service and also the external service.

So, to address this we can cache at 2 levels; on the client side we can leverage ASP.NET Cache object and on the core API side we can use local caching.

The proxy WCF service has ASPNET compatibility mode turned on so that its invocable by Javascript/AJAX, this also allows us to tie into the ASP.NET execution pipeline and hence access the Cache object,

   1: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   2: public class Service1 : IService1
   3: {
   4:  
   5:     public string[] GetList(string prefixText, int count)
   6:     {
   7:         if (HttpContext.Current.Cache["items"] == null)
   8:         {
   9:             Debug.WriteLine("Adding Item to Cache");
  10:             var items = Enumerable.Range(1, 10).Select(i => i.ToString()).ToArray();
  11:             HttpContext.Current.Cache.Insert
  12:                 (   "items", 
  13:                     items, 
  14:                     new CacheDependency(HttpContext.Current.Server.MapPath("Web.config")),
  15:                     DateTime.UtcNow.AddMinutes(int.Parse(ConfigurationManager.AppSettings["CacheExpirationInMinutes"])),
  16:                     Cache.NoSlidingExpiration
  17:                 );
  18:             return items;
  19:         }
  20:         else
  21:         {
  22:             Debug.WriteLine("Read Item from Cache");
  23:             return HttpContext.Current.Cache["items"] as string[];
  24:  
  25:         }
  26:     }
  27: }

 

Basically we’ve set up a dependency to changes in web.config and also to a time interval in minutes specified in web.config as an AppSetting, this means that if the time specified elapses or web.config changes, the cache is invalidated.

This does the trick for now, if I get a chance I’ll put in the caching mechanism in the core API as well. My primary choice is using the Caching application block, but that is a post for another day.

Happy coding.