Wednesday, 5 March 2014

Entity Framework Code First Generic Entity store operations

This article will discuss how generic entity store operations towards a data context can be used with EF Code First. This is tested with EF 6. First, define an interface with the often used generic entity store operations:

using System;
using System.Data.Entity;

namespace TestEFCodeFirst1
{

    public interface IRepo : IDisposable
    {

        T Insert<T>(T item, bool saveNow) where T : class;

        T Update<T>(T item, bool saveNow) where T : class;

        T Delete<T>(T item, bool saveNow) where T : class;

        int Save(); 

    }

}

Then implement this interface:

using System.Data.Entity;

namespace TestEFCodeFirst1
{
    
    public class Repo<TContext> : IRepo
        where TContext : DbContext, new()
    {

        public Repo()
        {
            Context = new TContext(); 
        }

        protected TContext Context { get; private set; }

        #region IRepo Members

        public T Insert<T>(T item, bool saveNow) where T : class
        {
            Context.Entry(item).State = EntityState.Added;
            if (saveNow)
                Context.SaveChanges();
            return item; 
        }

        public T Update<T>(T item, bool saveNow) where T : class
        {
            Context.Entry(item).State = EntityState.Modified;
            if (saveNow)
                Context.SaveChanges();
            return item; 
        }

        public T Delete<T>(T item, bool saveNow) where T : class
        {
            Context.Entry(item).State = EntityState.Deleted;
            if (saveNow)
                Context.SaveChanges();
            return item; 
        }

        public void Dispose()
        {
            Context.Dispose(); 
        }

        #endregion

        #region IRepo Members


        public int Save()
        {
            return Context.SaveChanges(); 
        }

        #endregion
    }

}

Next, create a simple DbContext to test out:

  
  public class DemoDbContext : DbContext
    {


        public DemoDbContext() : base("EFCodeFirstDemoDb1")
        {
            
            
        }


        public DbSet<Student> Students { get; private set; }

    }


An example of using this db context in a derived repo class is shown next:

public class DemoRepo : Repo<DemoDbContext>
{

}

The next code shows how to use this extension method:

using System;
using System.Data.Entity;

namespace TestEFCodeFirst1
{
    class Program
    {
        static void Main(string[] args)
        {

            Database.SetInitializer(new Init()); 

            using (var repo = new DemoRepo())
            {
                repo.Insert(new Student { Name = "Hardy", DateAdded = DateTime.Now,
                LastMod = DateTime.Now}, true);

                repo.Insert(new Student
                {
                    Name = "Joey",
                    DateAdded = DateTime.Now,
                    LastMod = DateTime.Now
                }, true);                

            }
        }

    }
}


To automatically patch your database do this:

In package-manager console type: Enable-Migrations In the configuration class, set AutomaticMigrationsEnabled to true.

namespace TestEFCodeFirst1.Migrations
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    internal sealed class Configuration : DbMigrationsConfiguration<TestEFCodeFirst1.DemoDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }

        protected override void Seed(TestEFCodeFirst1.DemoDbContext context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
}


Add an Init class:

using TestEFCodeFirst1.Migrations;

namespace TestEFCodeFirst1
{

    internal class Init : System.Data.Entity.MigrateDatabaseToLatestVersion
    {

    }
}

This explains what is done in the line further up: Database.SetInitializer(new Init());

No comments:

Post a Comment