The short example about Entity Framework 4 CTP4 - Part 1

A few days ago, I have read an article from Mr. huyrua, the person that I have a deep respect. The code that he implemented is very good to me. And I have an idea for implementing something in Entity Framework 4. You can go to http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern and see the best solution on multiple ObjectContext, according to me; it is a best solution in Entity Framework.

Microsoft just released Microsoft ADO.NET Entity Framework Feature Community Technology Preview 4 in 2010/07/13. And I really interested in it. In this new release, I found many features very cool. And now they support Convention over Configuration on DbContext class, instead of ObjectContext class in old version. So I want to explore it in this post. Because this post maybe long, so I divided into 3 parts:

Part 1: Step up ADO.NET Entity Framework 4 CTP4

  • Prepare tool for stepping up EF 4

  • The first introduce about my approaches

  • Build the heart of EF4 (Entity)

  • Mapping entity with database table

  • Build your DbContext, DbContext factory

Part 2: Repository and Unit of Work on Entity Framework 4

  • Create the repository for persistence ignorance

  • Unit of Work on EF4

Part 3: Invoke store procedure in ADO.NET Entity Framework 4

  • Come with Entity Framework extensions

  • Talk about Materializer and DbCommand

  • Build Contract Model for storing result that return from store procedure

  • Re-code the DbContext for mapping store procedure

Part 1: Step up ADO.NET Entity Framework 4 CTP4

  • Prepare tool for stepping up EF 4

If you want to use EF 4 CTP4, you must download it at http://www.microsoft.com/downloads/details.aspx?FamilyID=4e094902-aeff-4ee2-a12d-5881d4b0dd3e&displayLang=en

After installed it, you shall have enough tool for run EF 4 CTP, and the important dll that you should focus is Microsoft.Data.Entity.CTP.dll, product version is 4.0.30202.0. I usually copy it to one folder in my solution (at here I create a folder with named [References] and put that dll into this folder). Later we must reference it in our solution.

  • The first introduce about my approaches

Why did I choose EF4 CTP4? It is simple that EF4 CTP4 is code-first approach, so I can control more things in EF4. I can create model, mapping, db context… All things in code-first are code, I love it. I always resist the problem must read the auto-generated code from the Designer tool.

In old days, we usually use the ObjectContext for making the context for our solution. So you must create the EntityConnection instance for injecting it into the ObjectContext. It must be a concrete instance. Now in the CTP4 version, ADO.NET EF4 team introduced the new class with named DbContext, this class using Convention over Configuration for choosing the Database Provider. If you do not specific the connection name, DbContext will create the Database for you, and else DbContext will use the specific connection name that you pass into the ctor of DbContext class.

In an example in this post, I used DbContext for making Database Context.

  • Build the heart of EF4 (Entity)

In the new methodology, we do not care about creating database schema. We only focus on model and trivial model become the heart of modern software. In this example, I also focus on model and use the model to generate the database schema.

For easy to understanding, I will describe something about my example. I have the category that manages the news. Certainly, one category must have much news. And I keep this example as simple as possible.

After analyze, we have 2 tables, one is Category and one is News. And we also have one relationship on it (one category has many news).

Before implementing that 2 classes, I must build the base class for them, I called it is IEntity

    public interface IEntity
    {
        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>The id.</value>
        int Id { getset; }
    }

Next I created the based class that implement the IEntity, purpose of this base class is store something that you think it common and share for derive-classes.

    public abstract class EntityBase : IEntity
    {
        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>The id.</value>
        public virtual int Id { getset; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is delete.
        /// </summary>
        /// <value><c>true</c> if this instance is delete; otherwise, <c>false</c>.</value>
        public virtual bool IsDelete { getset; }

        /// <summary>
        /// Gets or sets the created date.
        /// </summary>
        /// <value>The created date.</value>
        public virtual DateTime CreatedDate { getset; }

        /// <summary>
        /// Gets or sets the description.
        /// </summary>
        /// <value>The description.</value>
        public virtual string Description { getset; }
    }

Read the code convention carefully before you start to code the entity class http://blogs.msdn.com/b/efdesign/archive/2010/06/01/conventions-for-code-first.aspx. Next I implement 2 classes (called it is entity) as below:

    public class Category : EntityBase
    {
        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        public virtual string Name { getset; }

        private readonly ICollection<News> _news;

        /// <summary>
        /// Initializes a new instance of the <see cref="Category"/> class.
        /// </summary>
        public Category()
        {
            _news = new List<News>();
        }

        /// <summary>
        /// Gets the news.
        /// </summary>
        /// <value>The news.</value>
        public virtual ICollection<News> News
        {
            [DebuggerStepThrough]
            get { return _news; }
        }
    }

And,

    public class News : EntityBase
    {
        /// <summary>
        /// Gets or sets the title.
        /// </summary>
        /// <value>The title.</value>
        public virtual string Title { getset; }

        /// <summary>
        /// Gets or sets the content.
        /// </summary>
        /// <value>The content.</value>
        public virtual string Content { getset; }

        /// <summary>
        /// Gets or sets the category.
        /// </summary>
        /// <value>The category.</value>
        public virtual Category Category { getset; }

        /// <summary>
        /// Initializes a new instance of the <see cref="News"/> class.
        /// </summary>
        public News()
        {
        }
    }

  • Mapping entity with database table

One feature that I like the EF4 CTP4 is we can create the mapping class for entity with the database schema. I used to coding on Fluent NHibernate for short time, when EF still supported the mapping class yet, and now it is the time I try to use the EF4 with mapping classes. Everyone also knew the hell when you used mapping file on XML in old days. That problem happened when you type wrong something in XML file. The errors happen consequence, I called it is chain of errors. Luckily, the community published the Fluent NHibernate, which is a good ORM mapping I have ever used. It is integrated with strong type for typing mapping configuration. And now the EF4 CTP4 also supports the same. And even it is easily understanding than Fluent NHibernate. Try to understanding the relationship in EF4 before you implement mapping class.

Mapping for Category:

    public class CategoryMapping : EntityConfiguration<Category>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CategoryMapping"/> class.
        /// </summary>
        public CategoryMapping()
        {
            HasKey(a => a.Id);

            Property(a => a.Id).IsIdentity();
            Property(a => a.Name).IsRequired().HasMaxLength(50);
            Property(a => a.IsDelete);
            Property(a => a.CreatedDate);
            Property(a => a.Description).HasMaxLength(500);

            MapSingleType(a => new
            {
                ID = a.Id,
                a.Name,
                a.IsDelete,
                a.CreatedDate,
                a.Description
            })
            .ToTable("Categories");
        }
    }

And News,

    public class NewsMapping : EntityConfiguration<News>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="NewsMapping"/> class.
        /// </summary>
        public NewsMapping()
        {
            HasKey(a => a.Id);

            Property(a => a.Id).IsIdentity();
            Property(a => a.Title).IsRequired().HasMaxLength(500);
            Property(a => a.Content).IsRequired().HasMaxLength(1000);
            Property(a => a.IsDelete);
            Property(a => a.CreatedDate);
            Property(a => a.Description).HasMaxLength(500);

            MapSingleType(a => new
            {
                ID = a.Id,
                CategoryId = a.Category.Id,
                a.Title,
                a.Content,
                a.IsDelete,
                a.CreatedDate,
                a.Description
            })
            .ToTable("News");
        }
    }

If you are familiar with Fluent NHibernate mapping, it is enough simple for you to understanding, isn’t it? If you are new person, it is not problems. Go to http://blogs.msdn.com/b/adonet/archive/2010/07/14/ctp4codefirstwalkthrough.aspx, read it, and you shall clear.

  • Build your DbContext, DbContext factory

Now, we shall start to investigate the DbContext, new features in CTP4, and next step we shall implementation the DbContext Factory for getting new DbContext’s instance. Because the DbContext is very complex and long code if your application become larger in the future, so I build it is a partial class and separated it to small classes.

    public partial class CSPDbContext : DbContext
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CSPDbContext"/> class.
        /// </summary>
        /// <param name="model">The model.</param>
        public CSPDbContext(DbModel model)
            : base("CallStoreProc", model)
        {
        }
     }
    public partial class CSPDbContext
    {
        /// <summary>
        /// Called when [model creating].
        /// </summary>
        /// <param name="modelBuilder">The model builder.</param>
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new CategoryMapping());
            modelBuilder.Configurations.Add(new NewsMapping());
        }

        /// <summary>
        /// Gets or sets the categories.
        /// </summary>
        /// <value>The categories.</value>
        public DbSet<Category> Categories { getset; }

        /// <summary>
        /// Gets or sets the news.
        /// </summary>
        /// <value>The news.</value>
        public DbSet<News> News { getset; }
    }

As you see on the OnModelCreating method, I overridden it and added 2 mapping files into ModelBuilder. And I also exported 2 DbSets for outside could access and used it.

Next, I must build the DbContext Factory, and first thing is a contract for it

And detail's implementation is

    public interface IDatabaseFactory : IDisposable
    {
        /// <summary>
        /// Gets this instance.
        /// </summary>
        /// <returns></returns>
        DbContext Get();
    }
    public class DatabaseFactory : IDatabaseFactory
    {
        private static readonly ModelBuilder builder = CreateModelBuilder();
        private readonly DbProviderFactory _providerFactory;
        private readonly string _connectionString;

        //private ObjectContext _objectContext;
        private DbContext _dbContext;

        /// <summary>
        /// Initializes a new instance of the <see cref="DatabaseFactory"/> class.
        /// </summary>
        /// <param name="providerFactory">The provider factory.</param>
        /// <param name="connectionString">The connection string.</param>
        public DatabaseFactory(DbProviderFactory providerFactory, string connectionString)
        {
            this._providerFactory = providerFactory;
            this._connectionString = connectionString;
        }

        /// <summary>
        /// Gets this instance.
        /// </summary>
        /// <returns></returns>
        public DbContext Get()
        {
            if (_dbContext == null)
            {
                var model = builder.CreateModel();

                _dbContext = new CSPDbContext(model);

                return _dbContext;
            }

            return _dbContext;
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        [DebuggerStepThrough]
        public void Dispose()
        {
            if (_dbContext != null)
            {
                _dbContext.Dispose();
            }
        }

        /// <summary>
        /// Creates the model builder.
        /// </summary>
        /// <returns></returns>
        private static ModelBuilder CreateModelBuilder()
        {
            ModelBuilder modelBuilder = new ModelBuilder();

            IEnumerable<Type> configurationTypes = typeof(DatabaseFactory).Assembly
                                                                          .GetTypes()
                                                                          .Where(type => type.IsPublic && type.IsClass && !type.IsAbstract && !type.IsGenericType && typeof(StructuralTypeConfiguration).IsAssignableFrom(type) && (type.GetConstructor(Type.EmptyTypes) != null));

            foreach (StructuralTypeConfiguration configuration in configurationTypes.Select(type => (StructuralTypeConfiguration)Activator.CreateInstance(type)))
            {
                modelBuilder.Configurations.Add(configuration);
            }

            return modelBuilder;
        }
    }

This is a factory that I learnt from Shrinkr project on Codeplex http://shrinkr.codeplex.com/

Part 2: Repository and Unit of Work on Entity Framework 4

Part 3: Invoke store procedure in ADO.NET Entity Framework 4

7 Comments

  • I do not like much the idea of ABCDbContext which is very specific, because every time we work with a new database model, say XYZ, we have to implement ABCDbContext. Also think about a model which has 1000 entities, we have to expose 1000 DbSets. There must be a better way, I think.

    Interesting post BTW, I am waiting for part 3 which I think quite fun.

    Good work!

  • Thank for your comments, aHuy. I like your ideas about DbSet. I will research about it in future. I think if I use the IoC container, I will not declare the ABCbContext in concrete instance.

  • after looking at you code, i don't see where the connection get passed to the DbContext in DatabaseFactory. great post and very helpful.

  • Hey, this was really helpful getting me started with EF4. Thank you!

  • Wonderful blog! I found it while surfing around on Yahoo News. Do you have any tips on how to get listed in Yahoo News? I've been trying for a while but I never seem to get there! Thanks

  • With havin so much content and articles do you ever run into any issues of plagorism or copyright violation? My website has a lot of unique content I've either created myself or outsourced but it appears a lot of it is popping it up all over the web without my permission. Do you know any solutions to help reduce content from being ripped off? I'd truly appreciate it.

  • I'm not sure why but this web site is loading very slow for me. Is anyone else having this issue or is it a issue on my end? I'll check back later and see if the problem still exists.

Comments have been disabled for this content.