【问题标题】:Repository & Unit of Work Pattern for Entity Framework using Dependency Injection使用依赖注入的实体框架的存储库和工作单元模式
【发布时间】:2011-03-28 11:37:32
【问题描述】:

我尝试了http://efrepository.codeplex.com 的 T4-Template,但我在 DI(使用 StructureMap)示例代码方面遇到了困难。对于像我这样的 DI 初学者来说,这还不够。它甚至没有编译。

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

【问题讨论】:

  • 如果您不熟悉 DI 模板,为什么要使用它?
  • 学习它:) 现在,我正在阅读/观看一些教程。在将其用于实际项目之前,我想知道自己在做什么。
  • 看看这篇文章:bit.ly/bF7jL3。它描述了一种 DI 和测试友好的存储库方式。

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


【解决方案1】:

我通常将以下设置与 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;
   }
}

你去。这是一大堆代码,但您几乎可以将其复制/粘贴到您的解决方案中,您应该一切顺利。

【讨论】:

    猜你喜欢
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多