EF CTP4 Tips & Tricks: Include with Lambda
Posted on July 14, 2010. Filed under: Entity Framework, Visual Studio | Tags: CTP4, EF, Entity Framework, Include, Visual Studio |
The release of Entity Framework Feature CTP4 was recently announced and included some walkthroughs touching on the core functionality included in the CTP. Over the next couple of weeks I’m going to post up a series of short articles that cover some of the finer points in the CTP.
The CTP includes some work called the Productivity Improvements for EF which aims to provide a simpler and more productive experience writing data access code with EF. Along with a bunch of conventions that take care of a lot of common tasks the Productivity Improvements also include some more subtle improvements over the core EF API. One of these is the introduction of an Include method that uses a lambda rather than strings to specify the include path.
Building a Quick Model
With the productivity improvements I can define a model using a set of POCO classes:
public class Blog
{
public int BlogId { get; set; }
public string Title { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Blog Blog { get; set; }
public ICollection<Comment> Comments { get; set; }
}
public class Comment
{
public int CommentId { get; set; }
public string CommentText { get; set; }
public Post Post { get; set; }
}
With the classes defined I just need to write a simple context:
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<Comment> Comments { get; set; }
}
Then I can use it for data access and EF will take care of discovering my model and creating a database for me:
using (var context = new BlogContext())
{
foreach (var blog in context.Blogs)
{
Console.WriteLine(blog.Title);
}
}
Existing Include
Include is a method we use in queries to specify that we should load related entities as well as the main type we are querying for, i.e. I want to query for a Blog but I want to bring all the Comments back into memory at the same time.
In EF4 (.NET 4.0, Visual Studio 2010) Include accepts a string to specify the related properties that should be loaded:
var blogsWithPosts = context.Blogs.Include("Posts");
The main complaints with this are the lack of intellisense, lack of compile time checking and that using refactoring in Visual Studio to rename the Blog.Posts property won’t update the string. Include was also an instance method on ObjectSet<T> so it had to be the first call when chaining query methods and wasn’t available if you’re set was typed as IObjectSet or IQueryable.
Include with Lambda
CTP4 includes a version of Include that accepts a lambda to specify the property to include. Note that this version of Include is an extension method so you will need to add a using for the System.Data.Entity namespace.
var blogsWithPosts = context.Blogs.Include(b => b.Posts);
This version of Include is an extension method on IQueryable<T> so you can add it after chaining other query methods:
var blogsWithPosts = context.Blogs
.Where(b => b.Title.StartsWith("A"))
.OrderBy(b => b.Title)
.Include(b => b.Posts);
Obviously not all implementations of IQueryable support Include, the implementation in CTP4 is EF specific and supports ObjectSet<T>, ObjectQuery<T> and DbSet<T> based queries. If the underlying implementation of IQueryable is something else then the extension method checks for a string based Include method to call, if there isn’t one then it is effectively a no-op.
Multi-Level Includes
Including more than one level in a hierarchy is still possible with the lambda Include, for reference properties you just dot through the hierarchy:
var commentsWithPostAndBlog = context.Comments.Include(c => c.Post.Blog);
For collections you use the Select method:
var blogsWithPostsAndComments = context.Blogs.Include(b => b.Posts.Select(p => p.Comments));
Summary
EF Feature CTP4 includes a new Include extension method in the System.Data.Entity namespace that allows you to specify include paths with a lambda. The Include extension method works with the new DbSet<T> along with existing ObjectSet<T> and ObjectQuery<T> types. This approach to specifying includes gives a better intellisense experience along with property name refactoring in Visual Studio and compile time checking of the include path.
Like this:
Like Loading...
Make a Comment
Leave a Reply
Comments RSS Feed
Where's The Comment Form?
[...] Feature CTP4, also recently dubbed “EF Magic Unicorn Edition”. In the last post we looked at Include with lambda and today we are going to look at the new Find [...]
EF CTP4 Tips & Tricks: Find « RoMiller.com
July 15, 2010
public ICollection Posts { get; set; }
Can you explain how to add new Post to uninitialized collection?
Might be this must be look like:
private ICollection posts;
public ICollection Posts { get { return posts ?? ( posts = new Collection()); }}
??
Thanks.
Roman
July 19, 2010
@Roman
The pattern you described is a common one, another alternative is to initialize the collection properties in the constructor. The pattern you suggested will potentially give better performance in situations where you are constructing a large number of objects because you only create the collection when actually needed.
I normally use List for the collection properties but you can of course use anything that implements ICollection.
EF doesn’t require that you initialize collections and will do it for you when it needs to add to the collection property (which is why the code in the post works).
romillerdotcom
July 19, 2010
[...] EF CTP4 Tips & Tricks: Include with Lambda [...]
C# Bits: EF CTP4 Released!
August 14, 2010
[...] EF4 .Include() Method w/ Lambda Support: Ever wanted to use a Lambda expression instead of a string parameter when eagerly loading associations in EF4 using the Include() method? This blog post shows you how you can. [...]
BusinessRx Reading List : August 29th Links: .NET, ASP.NET, IIS Express, Silverlight, Windows Phone 7
August 29, 2010
[...] EF4 .Include() Method w/ Lambda Support: Ever wanted to use a Lambda expression instead of a string parameter when eagerly loading associations in EF4 using the Include() method? This blog post shows you how you can. [...]
August 29th Links: .NET, ASP.NET, IIS Express, Silverlight, Windows Phone 7 - ScottGu's Blog
August 29, 2010
Why not use Single()?
Read: http://blogs.microsoft.co.il/blogs/shimmy/archive/2010/08/06/say-goodbye-to-the-hard-coded-objectquery-t-include-calls.aspx
weitzhandler
August 29, 2010
Will this support Include and a Where clause? Like:
.Include(b => b.Posts.Where(x=> x.Status == “Active”));
or something else like that?
John Bloom
August 30, 2010
WOW!
You didn’t mention that in your blog!
That’s most compelling, finally!!!
weitzhandler
August 30, 2010
@weitzhandler & @John Bloom
We would like to support filtering with Where in the future, which is why we opted for Select rather than Single.
But it’s not there in CTP4.
romillerdotcom
August 30, 2010
Now that’s what I’ve been waiting for,very nice.
alaa9jo
September 1, 2010
After rviewing this post I am still saying that the Select (“For collections you use the Select method”) should have been shorter, why use a new lmbda when this can be done in one word?
View my blog http://blogs.microsoft.co.il/blogs/shimmy
Even Single() is not the rightest way, an extra lambda is surely not.
I guess it’s too late anyway.
weitzhandler
September 1, 2010
I can not see the strongly typed version of Include? I have EF4 (.Net 4) and VS2010, its still exposing the string based Include.
James
September 15, 2010
@James:
Because you didn’t notice this in the article:
“Note that this version of Include is an extension method so you will need to add a using for the System.Data.Entity”.
That means you have to add:
Using System.Data.Entity;
Anonymous
September 15, 2010
I’m the one who posted this reply
alaa9jo
September 15, 2010
No, I’m the one who posted this reply!
Anonymous
August 15, 2012
@James
You also need to have EF Feature CTP4 installed as the lambda based include is still in preview; http://blogs.msdn.com/b/adonet/archive/2010/07/14/CTP4Announcement.aspx
~Rowan
romillerdotcom
September 16, 2010
[...] méthode d’extension similaire est inclue dans le Entity Framework Feature CTP4 (voir cet article pour plus de détails). Il est donc probable qu’elle finisse par être intégrée dans le [...]
[Entity Framework] Utiliser Include avec des expressions lambda « Blog .NET de Thomas Levesque
October 3, 2010
[...] similar extension method is included in the Entity Framework Feature CTP4 (see this article for details). So it is possible that it will eventually be included in the framework (perhaps in a [...]
[Entity Framework] Using Include with lambda expressions « Thomas Levesque's .NET blog
October 3, 2010
[...] · EF4 .Include()函数对Lambda的支持:在EF4里用Include()函数加载关联数据时,想用Lambda表达式替换字符参数?这篇文章就教你怎么做。 [...]
8月29号的精选好文链接-Scott Guthrie 博客中文版
October 15, 2010
Question on creating a DBContext derived context: is it necessary to declare a DbSet property for each entity class you create? For instance, if I have a Members entity and a MemberProfiles entity, but since a profile can belong only to one member and a member can only have one profile, they share an id field (MemberId). I would only access the profile data through the Member entity. Therefore, do I need to create a property DbSet MemberProfiles { get; set; }?
BTW,an excellent series. Actually the most clear, concise, comprehensive one I’ve been able to find on the Internet, to date.
Craig Shea
October 22, 2010
Hi Craig,
You can include extra entities that are not exposed in a DbSet in the OnModelCreating method:
public class MemberContext : DbContext
{
public IDbSet Members { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity();
}
}
Hope this helps,
~Rowan
romiller.com
October 30, 2010
I’m trying to use this on EF4 and VS2010.
I’ve included the
using System.Data.Entity;
but still has the only string version of include. Am I missing something ?
Dani
December 28, 2010
I would like to use Multi-Level Includes what you proposed, but I could not user more than one relatives. Does Include support only on relation?
Thanks in advance.
Nuri Yılmaz
January 20, 2011
[...] méthode d’extension similaire est inclue dans le Entity Framework Feature CTP4 (voir cet article pour plus de détails). Il est donc probable qu’elle finisse par être intégrée dans le [...]
[Entity Framework] Utiliser Include avec des expressions lambda | Blog .NET de Thomas Levesque
May 12, 2012