03 March 2017

The below code is running with entity framework 6. There are some improvements on Entity Framework Core, please check out my other blog: dotnetcore - entity framework LINQ evaluation, did you do it wrong?

DelegateDecompiler is a tool to decompile a delegate or method body to its lambda representaion.

Gains

It’s very handy when you write Entity framework LINQ expressions.

For example, if you have a table User with two columns: FirstName and LastName:


public class User{
    public string FirstName {get; set;}
    public string LastName {get; set;}

    [Computed]
    public string FullName => FirstName + " " + LastName; 
}

You can select users with a specified string in his Name by:


var name = "John";
var result = await DBContext.Users.Select(x => x.FullName.Contains(name)).DecompileAsync().ToListAsync();
//Or
var result = DBContext.Users.Select(x => x.FullName.Contains(name)).Decompile().ToList();

Without DelegateDecompiler, you can’t use FullName in the LINQ directly.

Pains

But I found wired behaviour when querying a entity with navigation properties. This is an example:

This one will not load the Customers eagerly:


var program = DbContext.Programs
    .Decompile()
    .Include(x=>x.Discounts.Select(b=>b.Customers.Select(c=>c.Customer)))
    .FirstOrDefault(x => x.Name.Contains("Jan"));

This one does:


var program = DbContext.Programs
    .Include(x=>x.Discounts.Select(b=>b.Customers.Select(c=>c.Customer)))
    .Decompile()
    .FirstOrDefault(x => x.Name.Contains("Jan"));

As you may have noticed, in the second code snipet. the Decompile() method is placed just before the last query.

Especially, if you disabled the Lazy Loading in Entity framework, the Customers property of Discount will be null. This is not acceptable.

So, remember always put Decompile() or DecompileAsync() at the end of the LINQ chain.



blog comments powered by Disqus