27 Feb 2011

A Smarter Entity Framework Include Method

6 Comments Uncategorized

One of the things I have always disliked about Entity Framework and their support for LINQ is that while your whole LINQ statement is compile time checked to make sure you didn’t fat finger any SQL statement, the Include() statement is not. 

How many times has something like this happened to you?

var account1001 = (new AccountEntities())
    .Accounts.Include("Userx")
    .Where(account => account.Id == 1001)
    .SingleOrDefault();

You might have noticed in the above that I probably wanted "Users" instead of "Userx". I don’t know about you but this happens to me all the time, and if the code was just compile time checks like the rest of the LINQ statement everything would be great and I would instantly catch the bug when the code was compiled.

I decided to make the Include method a little smarter with the use of Expressions and Extension methods, so that my include statements can be checked at compile time.  Here is how I did it.

public static ObjectQuery<T> Include<T>(this ObjectQuery<T> source, Expression<Func<T, object>> exp)
{
    var path = GetPath(exp);
    return source.Include(path);
}

private static string GetPath(Expression exp)
{
    switch (exp.NodeType)
    {
        case ExpressionType.MemberAccess:
            var name = GetPath(((MemberExpression)exp).Expression) ?? "";

            if (name.Length > 0)
                name += ".";

            return name + ((MemberExpression)exp).Member.Name;

        case ExpressionType.Convert:
        case ExpressionType.Quote:
            return GetPath(((UnaryExpression)exp).Operand);

        case ExpressionType.Lambda:
            return GetPath(((LambdaExpression)exp).Body);

        default:
            return null;
    }
}

The first method called Include has the same signature as the Include method included with the Entity Framework, except instead of taking a string for the path, the one I created above takes an Expression. The second method called GetPath, turns the expression in to a representitive string. So if your expression is:

x => x.Users

It will provide a string with the same signature:

"Users"

So here in the original statement from above using the new compile time checked include statement:

var account1001 = (new AccountEntities())
    .Accounts.Include(account => account.Users)
    .Where(account => account.Id == 1001)
    .SingleOrDefault();

As we were all taught in COMPSCI 101 or learned the hard way, magic strings are bad, and how Entity Framework implemented the Include method is a form of magic string that can easily cause unexpected bugs or even crashes.  So my effort above, hopefully will help some developer avoid a bug that should have been easily avoidable by a simple compile. 

17 Nov 2010

Entity Framework Repository Pattern

5 Comments Uncategorized

This is my first attempt at an Entity Framework (EF) based Repository Pattern.  I took a stab at this while working on a new project, and I am really liking the ease of use this is providing me.  So I thought I would share…

Before I get started, I wanted to make a special call out to Dane Morgridge’s EF Repository on CodePlex which is based on T4 templates.  His project originally got my gears turning as to how I would make my own repository pattern for EF.  Also I wanted to pre-text this blog post with the actual code which I have posted up on GitHub Gist:

https://gist.github.com/704330

First Things First

The first thing we need to do is abstract the ObjectContext so that we can unit test against our repositories, but with out saying more on the subject here is the interface we need:

public interface IObjectContext : IDisposable
{
    ObjectContextOptions ContextOptions { get; }

    TEntity CreateObject<TEntity>() where TEntity : class;
    IObjectSet<TEntity> CreateObjectSet<TEntity>() where TEntity : class;

    int SaveChanges();
}

This provides us with a nice defined interface for already implemented properties and methods on the ObjectContext.  And you extend your ObjectContext with the stub interface by doing the following:

public partial class YourContainer : IObjectContext
{
    IObjectSet<TEntity> IObjectContext.CreateObjectSet<TEntity>()
    {
        return CreateObjectSet<TEntity>();
    }
}

The YourContainer class is the one generated by EF.  Next thing we need is the Repository interface that is used for extending your entities.  You will probably recognize this because it is pretty standard CRUD interfaces that you will find on most repository patterns:

public interface IRepository<TEntity>
{
    IQueryable<TEntity> All();
    IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> expression);

    TEntity Create();

    void Add(TEntity entity);
    void Delete(TEntity entity);

    void Attach(TEntity entity);
    void Detach(TEntity entity);
}

You can see the base implementation of this interface on Gist.  Next and the part I love the most about my implementation is session wrapper object that works much like the System.Transaction objects in .NET and standard ObjectContext container examples that you will see on the web:

public interface IRepositorySession : IDisposable
{
    IObjectContext Container { get; }
    void Commit();
}

By adding the IDisposable interface to the session interface, I can wrap my repository calls in a using { … } block.  Which I thinks makes for a nice programing experience, and easier to read code where you don’t constantly have to set the connection you want the repository to run off of.  This pattern is based on my work from FluentCassandra.  You can view the implementation of this interface on Gist.

Using The Repository

The next part of this is to actually implement the repository for your entity.  The typical usage of this would be something like the following:

public class BlogRepository : Repository<Blog>
{
    public BlogRepository ()
        : base(RepositorySession.Current) { }

    public BlogRepository (IObjectContext container)
        : base(new RepositorySession(container)) { }

    public BlogRepository (IRepositorySession session)
        : base(session) { }

    public Blog Get(int id)
    {
        return Where(x => x.Id == id).SingleOrDefault();
    }

    // ... put your other methods ...
}

The constructor methods are probably what sticks out the most, the first one is the most important because it automatically instantiates it self based on the current repository session.  This automatic usage of the current sessions probably brings up more questions than answers, so hopefully this example of use answers most of those questions for you.

public ActionResult Update(int id)
{
    using (var db = new RepositorySession())
    {
        var repo = new BlogRepository();
        var blog = repo.Get(id);

        TryUpdateModel(blog, new[] {
            "Title", "Content", "Category", "Tags"
        });

        if (!ModelState.IsValid)
            return View(ModelState.GetErrors());    
        
        db.Commit();

        return View(blog);
    }
}

That looks pretty elegant and easy to understand, everything wrapped in RepositorySession using block automatically uses the container specified in the session.  And gets saved to the database when db.Commit() is called.

So now that we have gone through showing how you would use this repository pattern with your entities.  The last part to setting this up is providing your entity container type to the session class, so that it knows the entity type to instantiate when you create your session like above.

To use this pattern in your web project you would add the following registration code to your Application_Start in your Global.asax file. 

RepositorySession.DefaultContainerType = typeof(YourContainer);

This has dual use not only does it set the ObjectContext container for use in your production server, but with out needing to use IoC in your project (because sometimes it just isn’t necessary… gasp!), you can mock the IObjectContext in your tests so that you don’t need a database present to test. 

Conclusion

I just wanted to provide something useful, because me and my wife are expecting a baby girl in the next couple of days, and I don’t know how much time I will have to post to this blog before the new year.  Happy Holidays and wish me luck.

03 Dec 2009

Sometimes you just need to CodingHorror it!

4 Comments Uncategorized

The title of this post is a tongue-in-cheek reference to SubSonic’s inline query by the same name, which in turn is a reference to the blogger Jeff Atwood’s blog who you should all know.  Rob Conery, the SubSonic project leader, named the inline query class CodingHorror after he allegedly read Jeff Atwood’s post titled Embracing Languages Inside Languages, in which he bestowed the virtues of inline SQL inside your code, instead of the standard bequeathed statement that I bet you all have heard “We do all database work in stored procedures.”.  Jeff outlined his though process on ad-hoc vs stored procs as follows:

The Subsonic project attempts to do something similar for SQL. Consider this SQL query:

SELECT * from Customers WHERE Country = "USA"
ORDER BY CompanyName

Here’s how we would express that same SQL query in SubSonic’s fluent interface:

CustomerCollection c = new CustomerCollection();
c.Where(Customer.Columns.Country, "USA");
c.OrderByAsc(Customer.Columns.CompanyName);
c.Load();

I’ve mentioned before that I’m no fan of object-oriented rendering when a simple string will suffice. That’s exactly the reaction I had here; why in the world would I want to use four lines of code instead of one? This seems like a particularly egregious example. The SQL is harder to write and more difficult to understand when it’s wrapped in all that proprietary SubSonic object noise. Furthermore, if you don’t learn the underlying SQL– and how databases work– you’re in serious trouble as a software developer.

Enough of the History lesson, why are you writing this post

Well the reason for this post is two fold, I haven’t written a post in a couple of weeks, and I wanted to write about my own CodingHorror moment, while working with the Entity Framework, that solved a big problem I was having with getting the LIKE statement to work in LINQ.

I am working with a client of mine trying to expose their data to the web via a simple REST service.  Their whole database model has been constructed in the Entity Framework in a simple active record format.  One of the requirements, I was given, was to support wildcards on a couple of the input fields.  I thought this was no big deal, because I knew that the StartWith, EndsWith, and Contains methods of the System.String object, when used in LINQ, translated down to the SQL LIKE operator. 

However at the time I didn’t anticipate how much of a pain in the butt it was to actually figure out which of these three methods I should use depending on where the wildcard was placed in the string.  And how I would support a wildcard that was placed in the middle of a string.

Enter Entity Frameworks’s parameterized Where method

The parameterized Where method, of the ObjectQuery<T> object, really saved my butt.  It allowed me to produce the exact effect of the query I was looking for, and with out a lot of hacking.  Here is what I did:

if (!String.IsNullOrEmpty(toAddress))
	table = table.Where(
		"it.ToAddress LIKE @toAddress", 
		new ObjectParameter("toAddress", toAddress)
	);

var results = 
	from result in table
	where result.Account.AccountId == accountId
		&& result.DateTime >= startDate

return View(results.ToList());

The best part of the above code is that I can still use LINQ, and jump in to standard SQL syntax when the LINQ syntax fell short. 

This is my opinion gives the Entity Framework a step above the rest, because it means that I don’t have to complicate my life and my program by moving to a stored proc or making the whole select statement inline-SQL (which I wouldn’t ever do). 

Features like this that make developing software easier, and obviously have the programmer in mind, are what we should all strive for.  I like this for the very fact that the Entity Framework team has acknowledged that LINQ, while a wonderful addition to .NET, doesn’t meet all the needs for pulling data from the database and they sought to minimize the short comings by allowing developers to jump back in to the natural SQL language.  This is a wonderful addition in my book.