Category Archives: CodeProject

Implementing pub-sub using MSMQ in 15 minutes

Requirements:

1. Install MSMQ. By default the service is not enabled. To do this on Windows 7:

a. Launch the Control Panel and click on Programs | Turn Windows features on or off.
b. Select Microsoft Message Queue (MSMQ) Server.
c. Under this option, select MSMQ HTTP Support and Multicasting Support.
HTTP Support provides the ability to send messages across the internet.
Multicasting provides the ability for publish subscribe.

2. Click OK.
3. Open Computer Manager to confirm that you have a new listing under Services and Applications called Message Queuing with Outgoing, Private and System Queue folders.

Implementing Pub/Sub using MSMQ
1. Create a new C# Console Project.
2. Add reference to System.Messaging dll.
3. Modify Program.cs to look like follows:

    class Publisher
    {
        static void Main(string[] args)
        {
            //1. establish the queue
            using (var helloQueue = new MessageQueue("FormatName:MULTICAST=234.1.1.1:8001"))
            {
                while (true)
                {
                    var stopWatch = new Stopwatch();
                    stopWatch.Start();

                    //2. create a message, that can be anything since it is a byte array
                    for (var i = 0; i < 1000; i++)
                    {
                        SendMessage(helloQueue,
                            string.Format("{0}: msg:{1} hello world ", DateTime.UtcNow.Ticks, i));
                        Thread.Sleep(10);
                    }

                    stopWatch.Stop();
                    Console.ReadLine();

                    Console.WriteLine("====================================================");
                    Console.WriteLine("[MSMQ] done sending 1000 messages in " + stopWatch.ElapsedMilliseconds);
                    Console.WriteLine("[MSMQ] Sending reset counter to consumers.");

                    SendMessage(helloQueue, "reset");
                    Console.ReadLine();
                }
            }

        }

        private static void SendMessage(MessageQueue queue, string content)
        {
            //3. send the message
            queue.Send(content);
            Console.WriteLine(" [MSMQ] Sent {0}", content);
        }
    }

4. Create a new C# console project and add a reference to the System.Messaging dll.
5. Modify Program.cs to look like this:

  class Subscriber
    {
        static void Main(string[] args)
        {
            int messagesReceived = 0;
            var messages = new Queue<string>(5000);
            var filePath = typeof (Subscriber).FullName + ".txt";
            var path = @".\private$\hello-queue";

            using (var helloQueue = new MessageQueue(path))
            {
                helloQueue.MulticastAddress = "234.1.1.1:8001";
                while (true)
                {
                    var message = helloQueue.Receive();
                    if (message == null)
                        return;

                    var reader = new StreamReader(message.BodyStream);
                    var body = reader.ReadToEnd();

                    messagesReceived += 1;

                    messages.Enqueue(body);
                    Console.WriteLine(" [MSMQ] {0} Received {1}", messagesReceived, body);

                    if (string.CompareOrdinal("reset", body) == 0)
                    {
                        messagesReceived = 0;
                        File.WriteAllText(filePath, body);
                        messages.Clear();
                    }
                }
            }
        }
    }

Some implementation notes

1. Publish/subscribe requires a different queue path format. For fire and forget, the queue format is .\private$\hello-queue if sending to a private queue. For pub/sub, we need a multicast address in the form FormatName:MULTICAST=234.1.1.1:8001.
2. Messages received are not exactly same as sent. By default MSMQ uses an XML serializer so our plain string is now wrapped in an XML tag.
3. A multicast subscriber queue is just a regular queue with a multicast address. So you can create many different queues with different names with the same multicast address to receive the same message from the publisher.
4. You can have many publishers and many subscribers. All the subscribers receive all of the messages from each publisher.

Practical usage of C# covariance

Variance is a .NET 4.0 concept that allows implicit conversion between instances of generic types. In other words, it permits the corresponding C# compiler (same applies to Visual Basic) to perform implicit type conversions between instances of generic types whose parameters are in the same inheritance chain.

Consider two type definitions:

public class Vehicle {}
public class Bicycle: Vehicle{}

Using generic interfaces for illustration, a generic interface is covariant in T, if an instance instantiated with type T can be replaced with another instance instantiated with type T1 where T1 derives from T, without need of an explicit cast. IEnumerable<T> is covariant, means that an instance of IEnumerable<Vehicle> can be substituted with an instance of IEnumerable<Bicycles> without requiring an explicit cast.

In code:

IEnumerable<Vehicle> vehicles = new List<Vehicle>();
IEnumerable<Bicycle> bikes = new List<Bicycle>();

// covariance allows us to do
vehicles = bikes; 

This is one of those tricky concepts to wrap one’s head around, so in this blog post I give a practical usage of the covariance.

Consider an abstract class, called Parser created for the purpose of parsing files of a given extension. This abstract class will contain an abstract method that should be overridden with actual parsing logic. The class is given as follows:

public abstract class Parser
{
    // other code omitted for clarity
    public abstract ParseResult<IEntity, IParseContext> Parse(string resourcePath);
}

where the return type definition is defined as:

  public class ParseResult<T, TContext>
    {
        public ParseResult(IEnumerable<T> data, IList<ParseError> errors, TContext context) 
        {
            Context = context;
            Errors = errors;
            Data = data;
        }

        public IEnumerable<T> Data { get; private set; }
        public IList<ParseError> Errors { get; private set; }
        public TContext Context { get; private set; }       
    }

Next, consider a concrete implementation as follows:

public class PrnParser : Parser 
{
    private readonly IAipGateway _aipGateway;
    public PrnParser(IAipGateway aipGateway)
    {
       _aipGateway = aipGateway;
    }
 public override ParseResult<IEntity, IParseContext> Parse(string resourcePath)
        {
            var args = new PrnParseArguments(DateTime.UtcNow, _aipGateway, new BufferedTextFileReader(resourcePath));
            return Parse<MeterReading, PrnParseArguments>(args);
        }

       private void ParseResult<MeterReading, PrnParseArguments> Parse(PrnParseArguments args)
       {
           // do the parsing here
       }
}

If you attempt to compile this, the compiler will issue an error indicating that IParseResult<MeterReading, PrnParseArguments> cannot be converted to ParseResult<IEntity, IParseContext> even though the class MeterReading implements interface IEntity and class PrnParseArguments implements interface IParseContext.

In .NET 3.5 and earlier, one way to solve this problem is via explicit casting. So you would do something like this:

public class PrnParser : Parser 
{
    public override ParseResults<IEntity, IParseContext> Parse(string resourcePath)
        {
            var args = new PrnParseArguments(DateTime.UtcNow, _aipGateway, new BufferedTextFileReader(resourcePath));            
            var parsedResult = Parse<MeterReading, PrnParseArguments>(args);
            return  new ParseResults<IEntity, IParseContext>(parsedResult.Data.Cast<IEntity>(), parsedResult.Errors, parsedResult.Context);            
        }
}

However, starting in .NET 4.0 there is an easier way.

What you need to do is define a generic covariant interface and use this interface as the return type of the abstract method. In this context, a covariant interface will allow implementations of the Parse method to return concrete implementations of IParseResult without requiring that explicit cast.

Such an interface could look like this:

   public interface IParseResult<out T, out TContext>
    {
        IEnumerable<T> Data { get; }
        IList<ParseError> Errors { get;  }
        TContext Context { get;  }
        bool Success { get; }
    }

and then we modify ParseResult<T, TContext> to inherit from our new covariant interface IParseResult as follows:

   public class ParseResult<T, TContext> : IParseResult<T, TContext> 
        where T : IEntity 
    {
        // other code emitted for brevity
    }

Note the out parameters indicating that this is a covariant interface. Changing the signature of the abstract method to return our new covariant interface allows the C# compiler to be able to deduce the appropriate is-a relationship between ParseResult<MeterReading, PrnParseArgumets> and IParseResult<IEntity, IParseContext>

It is also easy enough to see the effect of not making this interface covariant by removing either or both out parameters from IParseResult<IEntity, IParseContext>. When you do this, the original compiler error message re-appears. Please note that there are additional criteria that must be satisfied for a generic interface can be made covariant such absence of public property setters on the generic type. For example, if properties IParseResult.Data and IParseResult.Context had public property setters, this interface could not have been made covariant.

In another blog post, I will capture a practical usage of contravariance.

Handling load/save layout on Infragistics XamDataGrid when model changes

We have a data intensive WPF application that his heavily reliant on Infragistics’ XamDataGrid control for tabular representation of data.  Just to get a feel of how reliant we are on this grid, usage in the application is as follows:

  • 20 tabular data views, each hosting an instance of XamDataGrid.
  • Configurable number of map views hosting a map-tip displaying its data using XamDataGrid.
  • 8 configuration editors, using a typical master-details layout, with an instance of XamDataGrid comprising the major control in the master section of the view.
  • 3 notification windows that present errors, alerts or alarms, depending on how you call it, also using a master-details layout.

From a performance and stylistic point of view, XamDataGrid has mostly worked well.   From a usability perspective, despite some of its shortcomings, such as an innate inability to resize a column to display its longest content when selected column header is double-clicked, XamDataGrid, does scores some good points, especially since it allows grouping and field-reordering abilities.

Our users are allowed to re-order the grid layout according to their preference. With this flexibility, however, comes the additional requirement of being able to persist current layout for each and every instance of the grid used in the application as part of the user profile.  Some of our customers, with multiple monitor arrangements, would re-arrange the grid layout in all major tabular data views, saving this as a read-only profile, thereby preventing further modifications by users with restricted privileges.   These requirements, therefore, demand an ability to reliably save and restore the grid layout when its parent container is being unloading and reloaded from the visual tree, respectively, during window closure or complete application shutdown.

One of our customers reported that there was one view that was not persisting its grid layout to profile. This is a problem we were not able to duplicate in house, especially given that our deployment environment does not entirely mimic those of our customers.   Luckily, using privileged access to one of our customer environments, we were able to gain additional insights after experience the problem firsthand.

The Problem:

XamDataGrid exposes an API that provides an ability to save and restore the grid layout. The respective methods are DataPresenterBase.SaveCustomizations and DataPresenterBase.LoadCustomizations. In our application we use the overloads that take and return a string:

LoadCustomizations(string);
public string SaveCustomizations()

These methods mostly work well until your underlying model changes. To demonstrate this problem, we will use a concrete example.

Assume in v1 your application that displays a list of all classic cars in your geographic region of interest, you have defined Car model with the following properties:

 public class Car
    {
        public string Make { get; set; }
        public string Model { get; set; }
        public double RetailPrice { get; set; }
        public string Manufacturer { get; set; }
        public string Color { get; set; }
        public DateTime DateOfManufacture { get; set; }
    }

Assume that you ran v1 of your application and saved a grid layout that consisted of all of the properties in the Car model. In v1.1, you realized that properties Color and DateOfManufacture are no longer applicable to the model, for whatever reason, and removed them. If you attempt to load v1 profile into v1.1 of your application, this does not work. Also, the grid will no longer be able to load and save your customization.

To demo this, create a MainViewModel class that consist of a collection of cars and all commands required to interact with our grid as follows:

public class MainWindowViewModel
    {
        private string _layout;
        private readonly XamDataGrid _dataGrid;
        private string _layoutLocation = "XamDataGrid.Layout.v1.xml";
        public MainWindowViewModel(XamDataGrid dataGrid)
        {
            _dataGrid = dataGrid;
            Cars = new ObservableCollection<Car>();
        }

        public ObservableCollection<Car> Cars { get; set; }

        public ICommand LoadLayoutFromFileCommand
        {
            get
            {
                return new RelayCommand((args) => true, o =>
                {
                    var layout = File.ReadAllText(_layoutLocation);
                    var fields = typeof (Car).GetProperties().Select(p => p.Name).ToArray();
                    var validatedLayout = XamDataGridHelper.ValidDataGridLayoutCustomization(layout, fields);
                    _dataGrid.LoadCustomizations(validatedLayout);
                });
            }
        }

        public ICommand SaveLayoutToFileCommand
        {
            get
            {
                return new RelayCommand((args) => true, o =>
                {
                    var layout = _dataGrid.SaveCustomizations();
                    File.WriteAllText(_layoutLocation, layout);
                });
            }
        }


        public ICommand LoadLayoutFromMemoryCommand
        {
            get
            {
                return new RelayCommand((args) => true, o =>
                {
                    if (!string.IsNullOrEmpty(_layout))
                    {
                        _dataGrid.LoadCustomizations(_layout);
                    }
                });
            }
        }

        public ICommand SaveLayoutToMemoryCommand
        {
            get
            {
                return new RelayCommand((args) => true, o =>
                {
                    _layout = _dataGrid.SaveCustomizations();
                });
            }
        }

        public ICommand LoadDataCommand
        {
            get
            {
                return new RelayCommand((args) => true, o =>
                {
                    Cars.Clear();
                    
                    Cars.Add(new Car {Make = "Toyota", 
                        Model = "Tercel", 
                        RetailPrice = 250,
                        Color = "#FF0000", 
                        DateOfManufacture = new DateTime(1975, 1, 1),
                        Manufacturer = "Toyota"});
                    Cars.Add(new Car { Make = "Honda", 
                        Model = "Accord", 
                        RetailPrice = 500,
                        Color = "#FF0012",
                        DateOfManufacture = new DateTime(1980, 1, 1),
                        Manufacturer = "Honda" });
                    Cars.Add(new Car { Make = "BMW",
                        Model = "M5", 
                        RetailPrice = 12000,
                        Color = "#FF6666",
                        DateOfManufacture = new DateTime(1985, 11, 1),
                        Manufacturer = "Bayerische Motoren Werke" });
      
                    _dataGrid.DataSource = Cars;
                });
            }
        }

        public ICommand ClearGridCommand
        {
            get
            {
                return new RelayCommand((args) => true, o =>
                {
                    _dataGrid.DataSource = null;
                });
            }
        }

        public class RelayCommand : ICommand
        {
            private readonly Predicate<object> _predicate;
            private readonly Action<object> _action;

            public RelayCommand(Predicate<object> predicate, Action<object> action)
            {
                _predicate = predicate;
                _action = action;
            }

            public void Execute(object parameter)
            {
                _action.Invoke(parameter);
            }

            public bool CanExecute(object parameter)
            {
                return _predicate.Invoke(parameter);
            }

            public event EventHandler CanExecuteChanged;
        }
    }

Since we do not want the grid to automatically generate the layouts for us, create a FieldLayoutFactory that creates a field layouts based on properties of our data as follows:

  public class FieldLayoutFactory
    {
        public static FieldLayout CreateFieldLayout(Type type)
        {
            var properties = type.GetProperties(BindingFlags.Public);

            var fl = new FieldLayout();
            foreach (var property in properties)
            {
                fl.Fields.Add(new Field(property.Name, property.PropertyType));
            }

            return fl;
        }
    }

and to complete the code for this demo, this is a simple XAML for the main window.

<Window x:Class="XamDataGridFieldLayoutProblems.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dataPresenter="http://infragistics.com/DataPresenter"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
            <Button Content="Save Layout To File" Command="{Binding SaveLayoutToFileCommand}"/>
            <Button Content="Load Layout from File" Command="{Binding LoadLayoutFromFileCommand}"/>
            <Button Content="Save Layout to Memory" Command="{Binding SaveLayoutToMemoryCommand}"/>
            <Button Content="Load Layout from Memory" Command="{Binding LoadlayoutFromMemoryCommand}"/>
        </StackPanel>
        <StackPanel
            Grid.Row="1"
            Orientation="Horizontal">
            <Button Content="Load Data" Command="{Binding LoadDataCommand}"/>
            <Button Content="Clear Grid" Command="{Binding ClearGridCommand}"/>
        </StackPanel>
        <dataPresenter:XamDataGrid 
            x:Name="MyXamDataGrid"
            Grid.Row="2"
            DataSource="{Binding Cars}"/>
    </Grid>
</Window>

with the code behind:

 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainWindowViewModel(MyXamDataGrid);
            MyXamDataGrid.FieldLayouts.Add(FieldLayoutFactory.CreateFieldLayout(typeof(Car)));
        }
    }

With all of these parts in place, compile and run the application, assuming you have access to InfragisticsWPF3.DataPresenter.v12.1.dll and InfragisticsWPF3.v12.1.dll. I did not run this test with 13.1 of the Infragistics toolkit.

When you initially run the application, it does the usual stuff of creating our view model and initializing the grid. After the application has launched, click on button labeled Load Data. We should see data in our grid as follows:

Re-arrange the grid columns as you wish then click on the button to Save Layout to File. My re-arrangement is shown here:

Clicking on Save Layout to File should create an XML file in the same location as your application executable. Depending on how you re-arranged your grid, the content of XamDataGridLayout.v1.xml should look somewhat like this:

<?xml version="1.0" encoding="utf-8"?>
<xamDataPresenter version="12.1.20121.1010" formatVersion="1.6">
  <fieldLayouts>
    <fieldLayout key="Car" fieldList="Make, Model, RetailPrice;Double, Manufacturer, Color, DateOfManufacture;DateTime">
      <fields>
        <field name="Make" extendedInfo="Make" Visibility="Visible" IgnoreFieldVisibilityOverrides="false" row="0" column="0" rowSpan="1" columnSpan="1" isCollapsedInLayout="false" />
        <field name="Model" extendedInfo="Model" Visibility="Visible" IgnoreFieldVisibilityOverrides="false" row="1" column="0" rowSpan="1" columnSpan="1" isCollapsedInLayout="false" />
        <field name="RetailPrice" extendedInfo="RetailPrice;Double" Visibility="Visible" IgnoreFieldVisibilityOverrides="false" row="0" column="1" rowSpan="1" columnSpan="1" isCollapsedInLayout="false" />
        <field name="Manufacturer" extendedInfo="Manufacturer" Visibility="Visible" IgnoreFieldVisibilityOverrides="false" row="1" column="1" rowSpan="1" columnSpan="1" isCollapsedInLayout="false" />
        <field name="Color" extendedInfo="Color" Visibility="Visible" IgnoreFieldVisibilityOverrides="false" row="0" column="2" rowSpan="1" columnSpan="1" isCollapsedInLayout="false" />
        <field name="DateOfManufacture" extendedInfo="DateOfManufacture;DateTime" Visibility="Visible" IgnoreFieldVisibilityOverrides="false" row="1" column="2" rowSpan="1" columnSpan="1" isCollapsedInLayout="false" />
      </fields>
    </fieldLayout>
  </fieldLayouts>
</xamDataPresenter>

Close and re-run your application without any code changes. After the window launches, click on Load Layout from File and observe that the grid layout is successfully restored.

Now, here comes the fun part ……

Comment out properties DateOfManufacture and Color from the Car model, preventing them from being included in our field layout based on the implementation of FieldlayoutFactory. Of course, you have to also comment our those lines that set the Car color during construction for your code to compile.

After making these changes, re-run the code. You should see only columns Make, Model, RetailPrice and Manufacturer columns. Now, click on Load Layout from File again and observe that nothing happens. Previous layout could not be restored. Re-arrange your grid the way you were expecting it to be restored (even though there are missing fields). Click button to save layout to memory. Next, change the ordering of the fields and click to load layout from memory and observe that the grid does not reload what we saved into memory. The grid is now stuck in some state that prevents it from loading or saving its layout.

The Solution
This new and strange behavior is happening because the grid loaded a field layout with columns that do not match the model or field layout definition is was initially provided. If you restore the properties in Car model that were commented out, or validate the layout before submitting to the grid by remove the two outdated fields, the problem goes away.

Add the following helper class to your solution.

        public class XamDataGridHelper
    {
        /// <summary>
        /// This method will remove any field not that is not contained in the list of columns.
        /// Comparison is done using the field name.
        /// </summary>
        /// <param name="fieldNames">list of field names to validate against</param>
        /// <param name="fieldList">comma seperated field list i.e content of fieldList node in layout. <fields></fields></param>
        /// <returns></returns>
        public static string ValidateFieldsLayoutFieldListNode(IList<string> fieldNames, string fieldList)
        {
            if (fieldNames == null)
                throw new ArgumentNullException("fieldNames");

            if (fieldNames.Count == 0)
                throw new ArgumentException("list of field names is empty");

            if (string.IsNullOrEmpty(fieldList))
                return fieldList;


            var fields = fieldList.Split(new[] { ',' });
            var fieldsToKeep = new StringBuilder();

            var splitter = new[] { ';' };
            for (var i = 0; i < fields.Length; i++)
            {
                var field = fields[i];
                var fieldParts = field.Split(splitter);
                if (fieldParts.Length > 0 && fieldNames.Contains(fieldParts[0].Trim()))
                {
                    fieldsToKeep.AppendFormat("{0}{1}", field, ", ");
                }
            }

            return fieldsToKeep.Remove(fieldsToKeep.Length - 2, 2).ToString();
        }

        /// <summary>
        /// This method will remove any field not that is not contained in the list of columns.
        /// Comparison is done using the field name.
        /// </summary>
        /// <param name="fieldNames">list of field names to validate against</param>
        /// <param name="fieldLayout">the field node to validate.  It must begin with <fields></fields></param>
        /// <returns></returns>
        public static XElement ValidateFieldLayoutFieldsNode(IList<string> fieldNames, XElement fieldLayout)
        {
            if (fieldNames == null)
                throw new ArgumentNullException("fieldNames");

            if (fieldNames.Count == 0)
                throw new ArgumentException("list of field names is empty");

            if (fieldLayout == null)
                throw new ArgumentNullException("fieldLayout");

            var fieldsInlayout = fieldLayout.Elements("field");
            var fieldsToKeep = new List<XElement>();
            foreach (var node in fieldsInlayout)
            {
                var name = node.Attribute("name");
                if (name != null && fieldNames.Contains(name.Value))
                {
                    fieldsToKeep.Add(node);
                }
            }

            fieldLayout.RemoveAll();
            fieldLayout.Add(fieldsToKeep);
            return fieldLayout;
        }

        /// <summary>
        /// This method validates a fieldLayout node by calling <code>ValidateFieldLayoutFieldsNode</code>
        /// and ValidateFieldsLayoutFieldListNode.  It attempts to remove any fields that are not part 
        /// of the validFields list.
        /// </summary>
        /// <param name="xml">the layout </param>
        /// <param name="validFields">valid fields to remove</param>
        /// <returns></returns>
        public static string ValidDataGridLayoutCustomization(string xml, IList<string> validFields)
        {
            var xdoc = XElement.Parse(xml);
            var fieldlayout = xdoc.XPathSelectElement("fieldLayouts/fieldLayout");

            var fieldListNode = fieldlayout.Attribute("fieldList");
            if (fieldListNode != null)
            {
                var fieldList = fieldListNode.Value;
                var cleanedFieldList = ValidateFieldsLayoutFieldListNode(validFields, fieldList);
                fieldListNode.SetValue(cleanedFieldList);
            }

            ValidateFieldLayoutFieldsNode(validFields, fieldlayout.Element("fields"));

            return xdoc.ToString();
        }
    }

Then modify the command handler that loads layout from file so the command definition looks like this:

   public ICommand LoadLayoutFromFileCommand
        {
            get
            {
                return new RelayCommand((args) => true, o =>
                {
                   <b> var layout = File.ReadAllText(_layoutLocation);
                    var fields = typeof (Car).GetProperties().Select(p => p.Name).ToArray();
                    var validatedLayout = XamDataGridHelper.ValidDataGridLayoutCustomization(layout, fields);</b>
                    _dataGrid.LoadCustomizations(validatedLayout);
                });
            }
        }

Compile and run the application. Now click on the button to Load Layout from File and observe that the layout is restored even though some of the fields are missing as show here:

These kinds of problems are difficult to encounter in house especially if there is a discrepancy between test and deployment environments. Also application/profile versioning is always a challenge. While we take full responsibility for this bug and fixed it, I think Infragistics could have done a better job here. If they had failed-fast by say, throwing an exception since provided layout does not match current grid layout, this problem would have been spotted earlier. Note that this is not a generalization or criticism of the quality of their coding guide lines but hopefully a means to share common pitfalls to be aware of when dealing with third party APIs. At least Infragistics has promised to fix this in a future release.

Hoping this helps others that run into a similar problem.

A Gentle Introduction to Entity Framework 6 from an NHibernate Perspective

If you have been using Hibernate/NHibernate for a while before the introduction of its fluent API, you are used to a certain workflow. You define your entity classes. Then you create a hibernate configuration file that defines mappings between the database tables and your entity classes. And that was about it.

With the Entity Framework 6, henceforth refereed to as EF6, you can several approaches: Database first, Model First or Code First. While each of these approaches cater to a different type of audience, they also present an immediate decision point of entry to the beginner, possibly hindering adoption and setting the stage ripe for a rough ride of perceptions whereby every aspect of the technology seems to appear overly engineered or complicated.

This blog attempts a gentle introduction to the Entity Framework. It is especially catered towards those developers who are used to the Hibernate workflow or similar. Such a workflow corresponds to the Entity Framework Code First approach. Along the way, commonalities and differences between both frameworks, within the context of what we are trying to achieve, will be highlighted.

Our Objective:
Create, read and update entities in a database using the Entity Framework.

Tools
If you like a hands-on approach and will like to code along, you will need the following tools:

1. Visual Studio 2012 (any edition)
2. SQL Server Management Studio Express 2012 available here: http://www.microsoft.com/en-us/download/details.aspx?id=29062
3. Adventure Works database, available here: http://msftdbprodsamples.codeplex.com/releases/view/55330
4. Entity Framework 6, available via NuGet.

Procedure:
The overall procedure can be summarized as follows:

1. Define entity classes that are representative of the database tables.
2. Create an Entity Framework database context that derives from System.Data.Entity.DBContext add a DbSet for every entity definition you want to query from the database.
3. Creating mapping classes that correlate properties in your entity model to columns in your database tables.
3. Create your Entity Framework configuration in app.config/web.config.
4. Add required configuration to your application’s configuration file
for the Entity Framework.

Please note that we will not be using any automatic code generation features of the Entity Framework. We choose to do every thing manually, fully acknowledging that certain aspects of the workflow such as mapping each column type to a respective CLR type, are faster done automated. However, just like making the 24 hour drive versus the 5 hour flight between Ottawa, Ontario, Canada to a place lie Sandestin, Florida, the former option gives you an opportunity to experience America’s landscape in its wonder. Whereas, the latter does not, quickly taking you from one comfort station to another, with no thrills or nothing to write home about. Doing things manually also gives us an opportunity to gain a better understanding of the framework by solving each potential problem as they arise.

Entity Framework 6 Default Behavior
Before proceeding it is worth noting certain default behaviors and assumptions exhibited by EF6, unless it is told otherwise:

  • Behavior: Pluralize a model to find corresponding table in database.
  • Behavior: Map a property in the model against a table column using the property name.
  • Behavior: Create a database to represent your Entity if one does not exist.
  • Assumption: Each entity has a primary key called Id or name of Entity’s type concatenated with “Id” defined in the corresponding table

As far as I know, Hibernate does not make any such assumptions, forcing you to explicitly create the context it will use to connect to the database, retrieve and map these entities.

Step 1: The Employee class:
This class is represented in HumanResources.Employee table of AdventureWorks2012.

Look at the table, schema, I manually created the following class:

public class Employee
    {
        public int Id { get; set; }
        public string NationalIDNumber { get; set; }
        public string LoginID { get; set; }
        public short OrganizationLevel { get; set; }
        public string JobTitle { get; set; }
        public DateTime BirthDate { get; set; }
        public char MaritalStatus { get; set; }
        public char Gender { get; set; }
        public DateTime HireDate { get; set; }
        public bool IsSalaried { get; set; }
        public short VacationHours { get; set; }
        public short SickLeaveHours { get; set; }
        public bool IsCurrent { get; set; }
        public DateTime ModifiedDate { get; set; }

        public override string ToString()
        {
            return string.Format("Employee Id {0} Login Id: {1}", Id, LoginID);
        }
    }

To keep things simple, columns OrganizationalMode and rowguid are not represented in the model as I could not readily figure out a corresponding CLR data type.

Step 2: Creating mappings to deal with model-table discepancies:
Since there is typically a discrepancy between our model and its associated table in the database, we need to create a type mapping.

For example the three default behaviors exhibited by EF6 will fail with the Employee model defined above because:
a: Our corresponding table is not called Employees. Instead it is HumanResources.Employee.
b: Properties IsSalaried and IsCurrent do not exist in the table. Corresponding table fields are CurrentFlag and SalariedFlag.
c: The primary key in HumanResources.Employee is BusinessEntityID and neither Id not EmployeeId.

In Hibernate you ALWAYs creating some sort of mapping either through configuration or recently via the Fluent API. In EF6, however, we only create a mapping if the default assumptions are false. I personally found this to be another decision point that could lead to some frustration but is not well documented. For the Employee model the default assumptions are false and therefore we will need to creating a mapping.

In EF6, we will create these mappings using a fluent API. This involves involves creating a class that derives from System.Data.Entity.ModelConfiguration.EntityTypeConfiguration
and defining mappings within the class constructor. For the Employee class, we need to specify the proper primary fields and create the correct mapping between fields IsCurrent and IsSalaried and their corresponding databae columns CurrentFlag and SalariedFlag respectively. The resulting code C# class looks like this:

   public class EmployeeMapping : EntityTypeConfiguration<Employee>
    {
        public EmployeeMapping()
        {
            // resolve discrepancy between default assumption on existence of Employees table
            ToTable("HumanResources.Employee");

            // to resolve discrepancy between primary key BusinessEntityID defined in database 
            HasKey(a => a.Id);

            // map Emplyee.Id to table column BusinessEntityID
            Property(e => e.Id).HasColumnName("BusinessEntityID");

            // map Employee.IsCurrent to table column CurrentFlag
            Property(a => a.IsCurrent).HasColumnName("CurrentFlag");

            // map Employee.IsSalaried to table column SalariedFlag
            Property(a => a.IsSalaried).HasColumnName("SalariedFlag");
        }
    }

Step 3: Registering type mappings with framework

In other to use these mappings, they must be registered with the framework. In NHibernate, we register type mappings in hibernate.cfg.xml or embed them into the assembly and let the framework resolve them automatically during runtime.

In EF6, the only way, unless someone can prove otherwise, to register these type mappings is by manually instantiating these classes in the appropriate EF database context. An EF database context is what your application uses to interact with the database. It is an instance of this class needs to be made aware of your type mappings and other configuration information that influences the framework’s behavior. In some ways, this class is similar in to the Hibernate Session object.

To connect to our AdventureWorks2012 database, we implement the following EF6 DbContext:

 public class AdventureWorksDbContext: DbContext
    {
        // register repository to Employees here
        public DbSet<Employee>  Employees { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // register Employee type mapping here
            modelBuilder.Configurations.Add(new EmployeeMapping());
        }
    }

As commented in the above file, we have registered our type mapping and created a repository to query for Employee types. Either of those lines are required to get EF6 communicating to the database.

Step 5: The Configuration:
Adding EF6 via NuGet adds an app.config file with the following:

<configSections>    
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
	
<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
    </providers>
  </entityFramework>
  

This is a standard snippet required to initialize EF6 in the your app domain. Nothing interesting here. However, we have one last EF6 default behavior to override. We want the framework to use our existing AdventureWorks2012 database instead of creating a new one. To do this, we need to add a connection string entry in our app.config, ensuring its name is exactly the same as the class name of our DbContext implementation as follows:

<connectionStrings>
    <add name="AdventureWorksDbContext" providerName="System.Data.SqlClient" connectionString="Data Source=localhost\SQLEXPRESS;Initial Catalog=AdventureWorks2012;Integrated Security=SSPI" />  
....
</connectionStrings>

This was another tripping point during my learning experience. And that is it folks. You have all the required bits to perform a simple CRUD operation to AdventureWorks2012 via the Entity Framework 6.

If you have followed so far, you should be able to write a simple console application to retrieve some employees:

   class Program
    {
        static void Main(string[] args)
        {
            IEnumerable<Employee> employees;
            using (var context = new AdventureWorksDbContext())
            {
                employees = context.Employees.Where(e => e.IsCurrent).ToArray();
            }

            foreach (var employee in employees)
            {
                Console.WriteLine(employee);
            }

            Console.ReadLine();
        }
    }

In a future blog post, I will look at relationships and stored procedures.

RESTful Webservice testing using cURL on Windows

Testing RESTful webservices on Windows can be done outside of the browser using an open source command tool called cURL, which can be donwloaded here: http://curl.haxx.se/download.html After downloading the Windows version based on your operation system, remember to add the location of the cURL binary to your system’s path environment variable.

The advantage of cURL over conventional forms such as browser is the ability to automate testing tasks and execute different types of HTTP requests. See the cURL online documentation for details.

Assume you have a RESTFul webservice available locally at http://localhost:8080/controlroomws. This webservice exposes a list of users via /UserList and the details of a specific user can be retrieved via /UserList/username. Through the webservice API, you can also persist users to a back end database using an HTTP POST request.

Say we will like to persist the following user to the back end database via the webservice API:

<user role="ROLE_OPERATOR" loginName="test_login1"></user>

Submitting an HTTP POST using inline XML will not work. For example, running this on the command line will return an exception:

curl -X POST -d "<userList xmlns="urn:user"><user role="ROLE_OPERATOR" loginName="chuck_norris"></user></userList>" -H "Content-Type: application/xml" --basic --user username:password http://localhost:8080/controlroomws/UserList/

as posted in this StackOverflow thread.

To circumvent this problem create an XML file containing your data and
submit to the RESTful service as follows:

curl -X POST -d @userList.xml -H "Content-Type: application/xml" --basic --user username:password http://localhost:8080/commandcontrolws/UserList

To confirm that your data has been persisted to the underlying data store, perform a HTTP GET request that will return the list of users as follows:

curl -X GET --basic --user username:password http://localhost:8080/commandcontrolws/UserList

To return details of the specific user you just added, issue another HTTP GET command:

curl -X GET --basic --user username:password http://localhost:8080/commandcontrolws/UserList/chuck_norris

Configuring NHibernate to execute a Stored Procedure that returns a result set

I recently spent about 5 hours trying to get NHibernate to successfully execute a stored procedure that returns a result set in SQL Server 2012. Given that it took me less than an hour to put all the pieces together for NHibernate to execute a similar stored procedure but one that returns a scalar, I thought this would be easy. Surely did not turn out that way.

This blog post explains exactly how you need to configure NHibernate to execute a stored procedure that returns a result set.

Tools
 The tools I used were Visual Studio 2010, SQL Studio Management Express 2012 and Express Profiler v2.0.   NHibernate version is 3.3.1.4000 pulled into the project via NuGet.

Requirement
Say, you have the following stored procedure:

if OBJECT_ID ( '[dbo].[sp_get_deactivation_list]', 'P' ) is not null
    drop procedure [dbo].[sp_get_deactivation_list];
go
create procedure [dbo].[sp_get_deactivation_list]
	@companyId int,
	@startDate DateTime,
	@endDate DateTime
as
begin
	select
   	        tblRadioinfo.ID as Id,
		tblRadioinfo.Mobile_ID as MobileId,
		tblRadioinfo.Radio_Address as RadioAddress,
		tblRadioinfo.Deactivation_Date as DeactivationDate
	from tblRadioinfo
	where tblRadioinfo.Radio_Type_ID in (2, 4, 7)
	and tblRadioinfo.Company_ID = @companyId
	and tblRadioinfo.Deactivation_Date <= @endDate
	and tblRadioinfo.Deactivation_Date >= @startDate
	and tblRadioinfo.Radio_Address in (select IMEI from [airtime_cdrs] where  Effective_Date > @startDate and Effective_Date < @endDate)
<p>	ORDER BY tblRadioinfo.Deactivation_Date
end

which when executed using the following simple test in SQL Studio Management Express 2012.

declare @route_id_param as varchar(10), @start_time as datetime, @start_date as datetime, @end_date as datetime
set @start_time = GETDATE()
set @start_date = CONVERT(DATETIME,'10/26/2013',101)
set @end_date = CONVERT(DATETIME,'12/26/2020',101) 
<p>exec dbo.sp_get_deactivation_list @companyId=1, @startDate = @start_date, @endDate = @end_date;
select execution_time_in_ms = DATEDIFF(millisecond, @start_time, getdate())
GO

returns two results as follows:

Id            MobileId              RadioAddress    DeactivationDate
3              MobileID_2        300034013417890             2020-12-26 00:00:00.000
4              MobileID_3        300034012356790             2020-12-26 00:00:00.000

Now, say you will like to use NHibernate to execute this stored procedure and return the same two records.

An Approach
Assume you have the following class and interface definitions:

 public class HibernateStoredProcedureExecutor : IExecuteStoredProcedure
    {
        private readonly ISessionFactory _sessionFactory;

        public HibernateStoredProcedureExecutor(ISessionFactory sessionFactory)
        {
            _sessionFactory = sessionFactory;
        }

        public IEnumerable<TOut> ExecuteStoredProcedure<TOut>(string procedureName, IList<SqlParameter> parameters)
        {
            IEnumerable<TOut> result;

            using (var session = _sessionFactory.OpenSession())
            {
                var query = session.GetNamedQuery(procedureName);
                AddStoredProcedureParameters(query, parameters);
                result = query.List<TOut>(); 
            }

            return result;
        }
        
        public TOut ExecuteScalarStoredProcedure<TOut>(string procedureName, IList<SqlParameter> parameters)
        {
            TOut result;

            using (var session = _sessionFactory.OpenSession())
            {
                var query = session.GetNamedQuery(procedureName);
                AddStoredProcedureParameters(query, parameters);
                result = query.SetResultTransformer(Transformers.AliasToBean(typeof(TOut))).UniqueResult<TOut>();
            }

            return result;
        }

        public static IQuery AddStoredProcedureParameters(IQuery query, IEnumerable<SqlParameter> parameters)
        {
            foreach (var parameter in parameters)
            {
                query.SetParameter(parameter.ParameterName, parameter.Value);
            }

            return query;
        }
    }

  public interface IExecuteStoredProcedure
    {
        TOut ExecuteScalarStoredProcedure<TOut>(string procedureName, IList<SqlParameter> sqlParameters);
        IEnumerable<TOut> ExecuteStoredProcedure<TOut>(string procedureName, IList<SqlParameter> sqlParameters);
    }

and somewhere within your project, you are invoking an instance of this class like this;

  public IEnumerable<Activation> GetDeactivationList(int companyId, DateTime startDate, DateTime endDate)
        {
             var sessionFactory = BuildSessionFactory();
            var executor = new HibernateStoredProcedureExecutor(sessionFactory);
            var deactivations = executor.ExecuteStoredProcedure<Activation>(
              "GetDeactivationList",
              new[]
                {
                    new SqlParameter("companyId", companyId), 
                    new SqlParameter("startDate", startDate), 
                    new SqlParameter("endDate", endDate), 
                });

            return deactivations;
        }

To get this all working, you will need a mapping for your stored procedure and one for the return type of your stored procedure, if your stored procedure is returning a result set of complex types.  The mapping file for the stored procedure looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping 
  xmlns="urn:nhibernate-mapping-2.2" 
  assembly="HGT.IridiumAirtime.Service" 
  namespace="HGT.IridiumAirtime.Service.Model">
  <sql-query name="GetDeactivationList" callable="true">
    <query-param name="companyId" type="int"/>
    <query-param name="startDate" type="DateTime"/>
    <query-param name="endDate" type="DateTime"/>
    <return class="Activation">
      <return-property column="Id" name="Id" />
      <return-property column="MobileId" name="MobileId" />
      <return-property column="RadioAddress" name="RadioAddress" />
      <return-property column="DeactivationDate" name="DeactivationDate" />
    </return>
    exec [sp_get_deactivation_list] @companyId=:companyId, @startDate=:startDate, @endDate=:endDate
  </sql-query>
</hibernate-mapping>

and for the return type of our stored procedure, which is not really associated with any table in the database, is listed below.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping 
  xmlns="urn:nhibernate-mapping-2.2" 
  assembly="HGT.IridiumAirtime.Service" 
  namespace="HGT.IridiumAirtime.Service.Model">
  <class name="Activation" >
    <id name="Id">
      <generator class="identity"/>
    </id>
    <property column="MobileId" name="MobileId" />
    <property column="RadioAddress" name="RadioAddress" />
    <property column="DeactivationDate" name="DeactivationDate" />
  </class>
</hibernate-mapping>

Once you have all of the aforementioned in place, you should be able to write and execute successfully a unit test against the GetDeactivationList method. If you use the same input parameters as those used earlier you should get the same two records.

The Gotchas
Bold lines in the aforementioned code sections were stumbling points and are worth mentioning. These were missing in my original iteration and were arrived at after numerous consultations against the document and StackOverflow

Since one cannot define a Hibernate mapping file without the Id column, you must add one, even if it means nothing to your entity.

 <id name="Id">
      <generator class="identity"/>
 <id/>

An Id column defined by the above Hibernate mapping mandates its inclusion in the return type definition of your stored procedure, hence the reason of this entry in the stored procedure’s mapping file:

    <return-property column="Id" name="Id" />

Otherwise, you will get an exception similar to this:

NHibernate.Exceptions.GenericADOException: could not execute query
[ exec [sp_get_deactivation_list] @companyId=@p0, @startDate=@p1, @endDate=@p2 ]
Name:companyId – Value:1 Name:startDate – Value:10/26/2013 12:00:00 AM Name:endDate – Value:12/26/2020 12:00:00 AM
[SQL: exec [sp_get_deactivation_list] @companyId=@p0, @startDate=@p1, @endDate=@p2] —> System.IndexOutOfRangeException: Id2_0_

An Id column defined in a Hibernate mapping file also mandates a corresponding public virtual property defined on the class. So we need this:

public virtual int Id { get; set; }

in the Activation class.

Finally, since you mapping has instructed NHibernate to expect an Id column in the result set, you must ensure one is returned by the stored procedure, hence the reason for this line:

assMobileRadio.ID as Id

In Conclusion
Relatively painful getting here but it now works. Hopefully this helps out others running into a similar problem. If any of my statements are technically inaccurate, please let me know. Also, much thanks to some good folks at StackOverflow for their help.