Before the introduction of dynamic features to C#, the obvious choice for implementing an ORM in C# was using a mapped approach. By “mapped” I mean the use of some kind of mapping between database columns and properties in entity classes that are known at compile-type. Most ORMs use a XML file or attributes to define the mapping.

By contrast, the default OR mapping approach in dynamically typed languages like Ruby and PHP, is “automagically” creating properties for database columns at run-time.

This dynamic approach might have been possible prior to C# 4 with reflection and/or CLR trickery, but thanks to the new C# dynamic features there now is a “clean” way to dynamically create properties in entity classes. I’m exploring how this might influence ORMs and C# data access in general.

Magic methods in PHP

I love comparisons and cross language thinking, so let’s first have a look at how things are done in a non-.NET language: PHP

In PHP you can dynamically create properties and methods. This done via magic overloading methods. Overloading methods are invoked when interacting with properties or methods that have not been declared. Examples of overloading methods are “__set” and “__get”. From the PHP documentation:

__set() is run when writing data to inaccessible properties.
__get() is utilized for reading data from inaccessible properties.

In other words, whenever you’re trying to get/set an undefined property, one of the magic overloading methods gets called. This makes magic methods ideal for dynamically creating objects from database rows in ORMs.

Very simple example in PHP pseudo code:

class Model {

    protected $columnData;

    function __construct() {
       Read column data into $columnData
    }

    public function __get ($_k) {
        return $columnData[$_k];
    }
}

This simple class stores column data in an array. The data can be accessed via property getters. For example, the get the value of column ‘Title’, we can write ‘$object->Title’

Magic methods are used by MVC frameworks and OR mappers like CakePHP to implement the ActiveRecord pattern in PHP.

Ruby

Of course I should also mention Ruby on Rails here. It is this framework that made the ActiveRecord pattern well known and popular amongst web developers.

In ruby, ‘method_missing’ is called as a last resort if the interpreter can’t find any declaration of a method call on an object. This method is used in ActiveRecord to implement dynamic finders (see below) and to allow access to attributes as were they first-class methods.

Equivalant of magic methods in C#

Since .NET 4.0, the magic of dynamically created properties is available in C#, via the new type dynamic.

If an (entity) class inherits from DynamicObject, you can override the TryGetMember and TrySetMember members methods, to mimic the behavior of magic methods in PHP or ‘method_missing’ in Ruby.

From the MSDN documentation for TryGetMember:

Classes derived from the DynamicObject class can override this TryGetMember to specify how operations that get member values should be performed for a dynamic object. When the method is not overridden, the run-time binder of the language determines the behavior. (In most cases, a run-time exception is thrown.)

In other words, TryGetMember/TrySetMember provide the means to dynamically “create” properties at run-time.

public class DynamicDictionary : DynamicObject
{
    // The inner dictionary.
    Dictionary<string, object> dictionary
        = new Dictionary<string, object>();

    // If you try to get a value of a property
    // not defined in the class, this method is called.
    public override bool TryGetMember(
        GetMemberBinder binder, out object result)
    {
        // Converting the property name to lowercase
        // so that property names become case-insensitive.
        string name = binder.Name.ToLower();

        // If the property name is found in a dictionary,
        // set the result parameter to the property value and return true.
        // Otherwise, return false.
        return dictionary.TryGetValue(name, out result);
    }

    // If you try to set a value of a property that is
    // not defined in the class, this method is called.
    public override bool TrySetMember(
        SetMemberBinder binder, object value)
    {
        dictionary[binder.Name.ToLower()] = value;
         return true;
    }
}

Of course, you don’t have to use a dictionary to store data that is accessed via TryGetMember. If the data comes from a database for example, a DataRow object can be used. Thomas Levesque provides a nice example on his blog:

public class DynamicDataRow : DynamicObject
{
    private DataRow _dataRow;

    public DynamicDataRow(DataRow dataRow)
    {
        if (dataRow == null)
            throw new ArgumentNullException("dataRow");
        this._dataRow = dataRow;
    }

    public DataRow DataRow
    {
        get { return _dataRow; }
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = null;
        if (_dataRow.Table.Columns.Contains(binder.Name))
        {
            result = _dataRow[binder.Name];
            return true;
        }
        return false;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        if (_dataRow.Table.Columns.Contains(binder.Name))
        {
            _dataRow[binder.Name] = value;
            return true;
        }
        return false;
    }
}

Now we can access columns from the datarow via “virtual” properties:

var bornInThe20thCentury = from r in table.AsEnumerable()
                           let dr = r.AsDynamic()
                           where dr.DateOfBirth.Year > 1900
                           && dr.DateOfBirth.Year <= 2000
                           select new { dr.LastName, dr.FirstName };

foreach (var item in bornInThe20thCentury)
{
    Console.WriteLine("{0} {1}", item.FirstName, item.LastName);
}

The ExpandoObject

What I showed above, was how to create a wrapper around a DynamicObject. But instead of building your own wrapper, you can also use a build-in .NET wrapper class: ExpandoObject.

dynamic dataObject = new ExpandoObject();
dataObject.test = "Dynamic Property";
Console.WriteLine(dataObject .test);

As this example shows, ExpandoObject offers a convenient way of adding methods and properties to a class at run-time.

The ExpandoObject can be useful in many situations, but I’d rather use the DynamicObject wrapping technique when dynamically creating properties for an entity class, because it provides more freedom in how to store and access the data internally.

Querying dynamic objects

Dynamic Finders

In ActiveRecord, dynamic finders can be used to query the database. ActiveRecord provides the general Find(conditions) method. On top of that, dynamic finders can be used. These are dynamically created methods that are specific to a model. For example, with PHP ActiveRecord you can write:

$book = Book::find_by_title('War and Peace');

Instead of:

$book =  Book::find(array('conditions' => "title = 'War and Peace'"));

Since .NET 4.0, we can do something similar in C#, via TryInvokeMember. Although dynamic find methods provide more convenience that their static counterpart, they also introduce a tight coupling between entity classes names and the rest of your code. Changing a class name, means changing method names in (potentially) many places. I don’t like this.

Dynamic Linq

Another approach would be to use Linq. Current .NET LINQ implementation does not allow dynamic objects in lambda expressions. But with some modifications, dynamic objects can used with Linq anyway. Quote from David Fowler:

We’ve successfully abused the new dynamic feature to get it working with LINQ. Hopefully in some future version of C# and VB we get deeper integration with LINQ and dynamic.

The future

I wonder how, and if, existing ORM’s, like NHibernate and Entity Framework will use .NET dynamic features in new versions. You can argue that statically typing entity classes are safer, because types can be checked at compile time.

On the other hand, dynamic entities provide more flexibility which might come in handy when the database schema changes. And, because manually defined object-database mapping can be reduced to minimum (often, only associations need to be defined), most users find dynamic ORMs like ActiveRecord easier to use than their statically typed counterparts like NHibernate.

Microsoft.Data

Concerning the last aspect, Microsoft has released a preview of a new data access library, Microsoft.Data.Dll, which is nothing more than a wrapper around ADO.NET that make data access in .NET easer for developers used to the way PHP handles things. It uses for example dynamic objects to provide easy access to data properties.

Many see Microsoft.Data as a way for Microsoft to reduce the barriers for developers to switch to the Microsoft platform. This probably true, since the target audience for Microsoft.data is differs completely from that of complex ORMs like Entity framework (which is by the way essentially also just a wrapper around ADO.NET). Quote from Scott Gu:

We’ve debated the role of ORMs for entry-level devs quite a bit (and have a dynamic ORM implemented – but which we didn’t ship with today’s preview). For someone who understand objects and classes they can be great. When we brought in web developers to use the product for a few days, though, one interesting data point that came up repeatedly was that about 80% of them had never even heard the term “ORM”. We found it took awhile for them to conceptually grok it – whereas adhoc SQL came much easier to them. It is something we are going to continue to work on finding the right balance on.

But many hard-core .NET developers and bloggers reacted very sceptical to Microsoft’s announcement, to say the least. The general criticism about Microsoft.Data is that encourages bad practices to novice developers. Unsurprisingly, That is also the often heard argument against PHP.

But does PHP really unleash indescribable evil upon humanity because novice developers can easily access to a MysQL database? I don’t think so. Of course, a lot of “dirty” code has been written for hobby projects and personal web sites, especially in the early days of the web. But most professional developers nowadays use very well structured and programmed frameworks like Zend and CakePHP. Furthermore, many skilled professional developers today who started as a hobby programmer, would not have started programming if it I weren’t for languages like PHP and Visual Basic.

Quote from Evan Nagle:

This [Microsoft.Data] isn’t the end of the world. There are people starving. There are wars. There are women being traded as sex slaves right outside my window in Honolulu. In sum, Microsoft.Data isn’t responsible for the totality of all human suffering.

I totally agree.

I would love to hear your thoughts in the comments…

Further reading

C# .NET

Other languages

4 Responses to “Data access using C# 4 dynamic features”

  1. chrelad says:

    This is great! Thanks :)

  2. C# is really powerful now.
    Dynamic language is the trend

  1. Data access using C# 4 dynamic features • Onderweg Blog…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

  2. [...] Data access using C# 4 dynamic features – “Before the introduction of dynamic features to C#, the obvious choice for implementing an ORM in C# was using a mapped approach. By “mapped” I mean the use of some kind of mapping between database columns and properties in entity classes that are known at compile-type.” [...]

Leave a Reply





Human Verification