存储库&使用依赖注入的实体框架的工作单元模式

时间:2011-03-28 11:37:33

标签: entity-framework dependency-injection repository-pattern unit-of-work

我尝试了来自http://efrepository.codeplex.com的T4模板,但我正在努力使用DI(使用StructureMap)示例代码。对于像我这样的DI初学者来说,这还不够。它甚至没有编译。

我已经使用非DI模板完成了一些示例项目。它效果很好。我喜欢它,它生成所有必要的存储库,我可以轻松地定制和扩展它们。但我不能让DI示例工作。有没有类似的项目(有更好的文档)?

1 个答案:

答案 0 :(得分:2)

我通常使用以下设置与EF端结构图:(支持自己,即将出现的代码)。

这是我们用来注入控制器的基本接口:

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();
}

这里考虑了EF的ISession实现:

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
    }
}

现在这个ISession实现注入不是很方便,因为虽然它很好且通用,但它没有默认的构造函数,所以解决它的方法是编写一个只暴露一个的小包装器无参数构造函数:

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

现在我们可以轻松注入它。我们在StructureMap中进行了如下设置:

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

如果你有一个MVC风格的控制器:

public class HomeController : Controller
{
   private readonly ISession _session;

   // ISession will be injected automatically
   public HomeController(ISession session)
   {
       _session = session;
   }
}

你去吧。这是一个很多代码,但你可以将它复制/粘贴到你的解决方案中,你应该很高兴。