Repository & Unit of Work Pattern for Entity Framework using Dependency Injection

后端 未结 1 558
梦毁少年i
梦毁少年i 2021-01-25 15:25

I tried the T4-Template from http://efrepository.codeplex.com, but I\'m struggling with the DI (uses StructureMap) Example code. It\'s just not enough for a DI beginner like me.

相关标签:
1条回答
  • 2021-01-25 15:50

    I normally use the following setup with EF end Structure map: (brace yourself, bunch o' code coming up).

    This is the base interface we'll use to inject our controllers:

    public interface ISession : IDisposable
    {
        void CommitChanges();
        void Delete<T>(Expression<Func<T, bool>> expression) where T : class, new();
        void Delete<T>(T item) where T : class, new();
        void DeleteAll<T>() where T : class, new();
        T Single<T>(Expression<Func<T, bool>> expression) where T : class, new();
        IQueryable<T> All<T>() where T : class, new();
        void Add<T>(T item) where T : class, new();
        void Add<T>(IEnumerable<T> items) where T : class, new();
        void Update<T>(T item) where T : class, new();
    }
    

    And here an ISession implementation with EF in mind:

    public class EntityFrameworkSession : ISession 
    {
        // MyContext is a class inheriting from EF's DbContext
        readonly DbContext _context;
    
        public EntityFrameworkSession(DbContext context)
        {
            _context = context;
        }
    
        public void CommitChanges()
        {
            _context.SaveChanges();
        }
    
        public void Delete<T>(Expression<Func<T, bool>> expression) 
            where T : class, new()
        {
            var query = All<T>().Where(expression);
            foreach (var item in query)
            {
                Delete(item);
            }
        }
    
        public void Delete<T>(T item) where T : class, new()
        {
            _context.Set<T>().Remove(item);
        }
    
        public void DeleteAll<T>() where T : class, new()
        {
            var query = All<T>();
            foreach (var item in query)
            {
                Delete(item);
            }
        }
    
        public void Dispose()
        {
            _context.Dispose();
        }
    
        public T Single<T>(Expression<Func<T, bool>> expression) 
            where T : class, new()
        {
            return All<T>().FirstOrDefault(expression);
        }
    
        public IQueryable<T> All<T>() where T : class, new()
        {
            return _context.Set<T>().AsQueryable();
        }
    
        public void Add<T>(T item) where T : class, new()
        {
            _context.Set<T>().Add(item);
        }
        public void Add<T>(IEnumerable<T> items) where T : class, new()
        {
            foreach (var item in items)
            {
                Add(item);
            }
        }
        public void Update<T>(T item) where T : class, new()
        {
            //nothing needed here
        }
    }
    

    Now this ISession implementation is not very handy to inject because, while being nice and generic, it doesn't have a default constructor, so the way to solve it is by writing a small wrapper that only exposes a parameter-less constructor:

    /// <summary>
    /// This is the EF site alternative
    /// </summary>
    public class SiteEFSession : EntityFrameworkSession
    {
        public SiteEFSession() : base(new MyContext())
        { }
    }
    

    Now we can easily inject it. We set it up in StructureMap as follows:

    ObjectFactory.Initialize(x =>
    {
        x.For<ISession>().Use<SiteEFSession>();
    });
    

    And if you have, for instance, an MVC style controller:

    public class HomeController : Controller
    {
       private readonly ISession _session;
    
       // ISession will be injected automatically
       public HomeController(ISession session)
       {
           _session = session;
       }
    }
    

    There you go. It's a helluva lot of code but you can pretty much copy/paste it into your solution and you should be good to go.

    0 讨论(0)
提交回复
热议问题