Living in the Tech Avalanche Generation

A practitioner’s introspective on technology

Archive for the 'ORM' Category

Entity Framework 4.0 Improvements

First up, let me just say that I’m quite pleased that my needs with respect to declaring my fetching intentions (eager and / or lazy), no longer will require the  assistance of hammer_and_nail2-211x300PostSharp to get the job done. PostSharp is a great tool but I really shouldn’t have had to use it to achieve working the way I wanted to, therefore POCO is a welcome addition even if it does force me into some things such as choosing ICollection for 1..M navigable relationships within my Domain Model (only if you want to use change tracking proxies).

I am not going to regurgitate the changes here, for a complete list of the changes and new features see the ADO.Net Team blog.

There seem to be several points along an axis of how POCO you can choose to be with Entity Framework 4.0. At this stage I have the feeling that I will fall into the camp that probably wont use the proxies for change tracking but I will reserve judgement on that and perhaps that decision will be best left as a case by case assessment for some.

The thing I like the most is the fact I can (as already stated) remove the smoke and mirrors from my past efforts to get (somewhat) transparent lazy loading and streamline my whole approach. I say ‘somewhat’ transparent due to the fact that DeferedLoading is still ultimately ‘opt in’ and hence if you wanted to be pedantic you could make a case that this is still explicit. See below.

context.ContextOptions.DeferredLoadingEnabled = true

I will follow up from this post will several more by examining  each constituent part in the new version of NFetchSpec for the Entity Framework version 4.0. NFetchSpec4Ef, provides a reusable approach to implementing Repositories, Fetching Strategies and Specifications. Fetching Strategies provide a unified way of declaring your intent when instructing the Entity Framework to fetch data. Specifications enables a functional approach to supplying dynamic query predicates and stays true to the patterns original intent, that being to provide a means to testing that an entity satisfies a given set of conditions. Repositories speak for themselves.

Share/Save/Bookmark

2 comments

Entity Framework Profiler with IronRuby and IronPython Scripting

ir_console_ef_profilerBecause I would like to write my Repositories and monitor their behaviour in the Profiler I decided that I could kill two birds with one console (so to speak). The first bird to kill involved my spending as much time as possible in the pursuit of both learning IronRuby and gaining better understanding of the more interesting problems that can be solved with dynamic languages implemented on top of the DLR. I can see the possibilities of hosting the DLR to provide scripting support to applications and after having implemented my own hosted IronRuby consoles I eventually decided to reuse one that was more fully featured, saving me quite a bit of time by best fitting the Profiler’s needs. The console I chose in the end was IronEditor which is available on codeplex. IronEditor is implemented as a Windows Forms application and so I did have to refactor it a little to make it work as User Control and have the UI behave correctly for asynchronous updates to the UI. Hosting the Windows User Control in the WPF Profiler was of course simple enough by leveraging the WindowsFormsHost.

I had already posted about what to expect from the next iteration of the Profiler and I won’t repeat it here, so if your new to the tool I suggest you look here. One further change I flagged was to remove WCF from the application and have the messaging occur via sockets. I decided against that change and chose instead (see below) to take the opportunity to demonstrate how to use WCF UnTyped Messages with a bit of IoC to achieve a more loosely coupled approach to handling messages. This approach requires writing specific handlers for specific messages that are not in any way coupled to the signature of any RPC / CRUD looking ServiceContract or the shape of any DataContract, and it is a style somewhat (largely) borrowed from NServiceBus. Here’s the code from the WCF Service and I will have more to say on that a bit later with a more detailed post.

Messaging

public void SendAny(Message message)
{
    object msg_in_body = null;

    var container =
        new Castle.Windsor.WindsorContainer();

    //get all the potential handlers in the assembly
    //NOTE: could load all these up at startup and call
    //to find one that matches from memory rather than
    //in the same iteration that adds the components
    //to the container.
    var libTypes = from a in Assembly.GetExecutingAssembly().GetTypes()
                   from i in a.GetInterfaces()
                   from ii in i.GetInterfaces()
                   from g in i.GetGenericArguments()
                   from gi in g.GetInterfaces()
                   where ii.IsAssignableFrom(typeof(IMessageHandler))
                   where gi.IsAssignableFrom(typeof(IMessage))
                   select new
                   {
                       TheType = a,
                       TheIface = i,
                       TheGeneric = g,
                       TheGenericIface = gi
                   };

    //iterate all the handlers
    foreach (var gen in libTypes)
    {
        container.AddComponent(gen.TheType.Name, gen.TheType);
        //attempt to deserialize using the current
        //handlers generic argument (the message)
        msg_in_body =
            MessageSerializer.DeserializeMessage
            (message, gen.TheGeneric);
        if (msg_in_body != null)
        {
            //resolve the message handler in the container
            var the_handler =
                container.Resolve(gen.TheType);
            var handle_method =
                the_handler.GetType().GetMethod(“Handle”);
            if(handle_method != null)
                handle_method.Invoke(the_handler,
                    new[] { msg_in_body });
        }
    }
}

The Messages And Message Handlers

public interface IMessage
{
    Guid MessageID { get; }
}

public interface IMessageHandler {  }

public interface IMessageHandler<TMessage> :
                 IMessageHandler where TMessage : IMessage
{
    void Handle(TMessage message);
}

public class EntityInterceptMessage : IMessage
{
    [XmlElement(Order = 1)]
    public Guid MessageID
    {
        get { return _id; }
        set { _id = value; }
    }

    [XmlElement(Order = 2)]
    public string SqlQueryText
    {
        get { return _sql; }
        set { _sql = value; }
    }

    [XmlElement(Order = 3)]
    public string ProcessID
    {
        get { return _processId; }
        set { _processId = value; }
    }

    //….message members etc

}

public class EntityInterceptMessageHandler :
             IMessageHandler<EntityInterceptMessage>
{
    public void Handle(EntityInterceptMessage message)
    {
        ProfilerModel.EntityMessages.Add(message);
        Console.WriteLine(message.EntityModelName);
    }
}

Running the Application

You can run this code and test it using a supplied IronRuby script named “run_profiler_script.rb”, just make sure you have the Northwind database installed , that the script gets the required changes to match your database details and that the the test projects DLL is ‘required’ from the appropriate location on your hard drive.

require ‘D:/simon.segal/Local Working/Org.TechA.EF.Profiler’ +
    ‘/Org.TechA.EF.Profiler.Tests/bin/Debug’ +
    ‘/Org.TechA.EF.Profiler.Tests.dll’

By downloading you will be accepting the code project open license for the SQL CodeBox control and the Apache License 2.0 for IronEditor, both of which have been integrated into this solution. You can download the Profiler from here.

UPDATE: (Sunday April 19th)

Apologies for having an earlier link to the code being incomplete. The problem has now been rectified.

Share/Save/Bookmark

5 comments

Entity Framework Profiler hosts IronRuby and IronPython

I mentioned recently that I wanted to add IronRuby scripting into the profiler so users could compose scripts and execute Entity Framework code directly from the Profiler itself. After looking around at how to host IronRuby in my own application it became clear very quickly that I was about to set out on building something quite redundantly. IronEditor, DLRPAD to name a few, offer this functionality, so all I needed was to grab one such tool whose license and functionality were a match. I decided on IronEditor. IronEditor is a Windows Forms application that embeds a IronRuby console and allows both IronRuby and IronPython scripting, so immediately I gained a benefit of adding support to both languages.

Unfortunately IronEditor has a lot of the required code embedded in a Windows Form causing me to rework the source a little to turn the Form in to a User Control which I can easily host in the profiler using the WPF Windows Forms Host. This will also require some reworking of the WCF code, as the client and server will be in the same application and to be frank WCF is overkill and I am going to refactor the messaging with sockets more than likely. It’s not quite ready but here’s a screen shot of what to expect.

Exhibit 1.0

PROF

Exhibit 1.0 demonstrates the an IronRuby script that works against one of my C# Entity Framework Repository libraries.

Exhibit 2.0

PROF_QUERY_IRON

Exhibit 2.0 displays the TSQL that is run as result of the one of the queries that are run by the IronRuby script.

Exhibit 3.0

PROF_QUERY_IRON_META

Exhibit 3.0 shows the Meta Data View also produced by running the same IronRuby script.

The IronRuby Script

require ‘System.Windows.Forms, Version=2.0.0.0, ‘ +
    ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′
require ‘D:/simon.segal/Local Working/Org.TechA.EF.Profiler’ +
    ‘/Org.TechA.EF.Profiler.Tests/bin/Debug’ +
    ‘/Org.TechA.EF.Profiler.Tests.dll’
require ‘System.Data, Version=2.0.0.0, ‘ +
    ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′
require ‘System.Data.DataSetExtensions, ‘ +
    ‘Version=3.5.0.0, Culture=neutral, ‘ +
    ‘PublicKeyToken=b77a5c561934e089′
require ‘System.Data.Entity, Version=3.5.0.0, ‘ +
    ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′
require ‘System.Core, Version=3.5.0.0, ‘ +
    ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′

$providerName = “System.Data.SqlClient”
$serverName = “boomer”
$databaseName = “Northwind”

#Initialize the connection string builder For the
#underlying provider.
$sqlBuilder = System::Data::SqlClient::
                SqlConnectionStringBuilder.new

#Set the properties For the data source.
$sqlBuilder.DataSource = $serverName
$sqlBuilder.InitialCatalog = $databaseName
$sqlBuilder.IntegratedSecurity = true

#Build the SqlConnection connection string.
$providerString =
    $sqlBuilder.ToString()

#Initialize the EntityConnectionStringBuilder.
$entityBuilder = System::Data::EntityClient::
    EntityConnectionStringBuilder.new

#Set the provider name.
$entityBuilder.Provider = $providerName

#Set the provider-specIfic connection string.
$entityBuilder.ProviderConnectionString = $providerString

#Set the Metadata location.
$entityBuilder.Metadata =
    “res://*/NorthWindModel.csdl|res://*/” +
    “NorthWindModel.ssdl|res://*/NorthWindModel.msl”

#get the connection string
$con = $entityBuilder.ToString()

puts $con

#set up the ObjectContext
$session = Org::TechA::EF::Profiler::Tests::NorthwindEntities.new($con)

#Get all the customers
$custs = $session.Customers

$custs.each {|cust| puts cust.CompanyName}

#Get all the orders
$orders = $session.Orders

$orders.each {|order| puts order.OrderID}

So more than just pictures?

I expect to have a working revision out within a week or so but the current version without the scripting ability is still available here.

Share/Save/Bookmark

1 comment

« Previous PageNext Page »

Creative Commons Attribution-ShareAlike 2.5 Australia
Creative Commons Attribution-ShareAlike 2.5 Australia