Entity framework 实体框架和工作单位

Entity framework 实体框架和工作单位,entity-framework,unit-of-work,Entity Framework,Unit Of Work,我正在使用EF/存储库/工作单元,但我很难理解一些细节。在UnitOfWork内部,我创建了一个新的EF DbContext(EmmaContext),但看看存储库内部,我铸造了它,我知道这是错误的,我如何正确地获得repo内部的上下文?也许我完全走错了路 以下是我的工作单元: //Interface public interface IUnitOfWork : IDisposable { void Commit(); } //Implementation public class U

我正在使用EF/存储库/工作单元,但我很难理解一些细节。在UnitOfWork内部,我创建了一个新的EF DbContext(EmmaContext),但看看存储库内部,我铸造了它,我知道这是错误的,我如何正确地获得repo内部的上下文?也许我完全走错了路

以下是我的工作单元:

//Interface
public interface IUnitOfWork : IDisposable
{
    void Commit();
}

//Implementation
public class UnitOfWork : IUnitOfWork
{
    #region Fields/Properties
    private bool isDisposed = false;
    public EmmaContext Context { get; set; }
    #endregion

    #region Constructor(s)
    public UnitOfWork()
    {
        this.Context = new EmmaContext();
    }
    #endregion

    #region Methods
    public void Commit()
    {
        this.Context.SaveChanges();
    }

    public void Dispose()
    {
        if (!isDisposed)
            Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        isDisposed = true;
        if (disposing)
        {
            if (this.Context != null)
                this.Context.Dispose();
        }
    }
    #endregion
}
以下是存储库:

//Interface
public interface IRepository<TEntity> where TEntity : class
{
    IQueryable<TEntity> Query();
    void Add(TEntity entity);
    void Attach(TEntity entity);
    void Delete(TEntity entity);
    void Save(TEntity entity);
}

//Implementation
public abstract class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
    #region Fields/Properties
    protected EmmaContext context;
    protected DbSet<TEntity> dbSet;
    #endregion

    #region Constructor(s)
    public RepositoryBase(IUnitOfWork unitOfWork)
    {
        this.context = ((UnitOfWork)unitOfWork).Context;
        this.dbSet = context.Set<TEntity>();
    }
    #endregion

    #region Methods
    public void Add(TEntity entity)
    {
        dbSet.Add(entity);
    }

    public void Attach(TEntity entity)
    {
        dbSet.Attach(entity);
    }

    public void Delete(TEntity entity)
    {
        dbSet.Remove(entity);
    }

    public IQueryable<TEntity> Query()
    {
        return dbSet.AsQueryable();
    }

    public void Save(TEntity entity)
    {
        Attach(entity);
        context.MarkModified(entity);
    }
    #endregion
}
//接口
公共接口假定,其中tenty:类
{
IQueryable查询();
无效添加(潜在实体);
无效附加(触角实体);
无效删除(潜在实体);
无效保存(潜在实体);
}
//实施
公共抽象类RepositoryBase:IRepository,其中tenty:class
{
#区域字段/属性
语境保护;
受保护的DbSet-DbSet;
#端区
#区域构造函数
公共存储库(IUnitOfWork unitOfWork)
{
this.context=((UnitOfWork)UnitOfWork.context;
this.dbSet=context.Set();
}
#端区
#区域方法
公共无效添加(TEntity实体)
{
添加(实体);
}
公共无效附加(TEntity实体)
{
附加数据集(实体);
}
公共作废删除(可撤销实体)
{
删除(实体);
}
公共IQueryable查询()
{
返回dbSet.AsQueryable();
}
公共作废保存(TEntity实体)
{
附(实体);
上下文。标记已修改(实体);
}
#端区
}
在本文中,您必须在存储库库中实现IUnitOfWork接口

我希望这有帮助。
关于

山姆:我通常对一个具体的存储库在ctor中执行具体的工作单元感到满意:

   public RepositoryBase(UnitOfWork unitOfWork)
   {
        this.context = unitOfWork.Context;
        this.dbSet = context.Set<TEntity>();
   }
公共存储库(UnitOfWork UnitOfWork)
{
this.context=unitOfWork.context;
this.dbSet=context.Set();
}
存储库和UoW通常协同工作,需要相互了解一点

当然,使用这些类的代码只知道接口定义,而不知道具体类型

这是最重要的

在他们的示例中,他们管理存储库的方式如下:

    private SchoolContext context = new SchoolContext();
    private GenericRepository<Department> departmentRepository;
    private GenericRepository<Course> courseRepository;

    public GenericRepository<Department> DepartmentRepository
    {
        get
        {

            if (this.departmentRepository == null)
            {
                this.departmentRepository = new GenericRepository<Department>(context);
            }
            return departmentRepository;
        }
    }
private SchoolContext=new SchoolContext();
私人通用存储部门存储库;
私人普通储蓄课程储蓄;
公共一般存储部门存储库
{
得到
{
if(this.departmentRepository==null)
{
this.departmentRepository=新的GenericRepository(上下文);
}
返回部门存储库;
}
}
您的工作单元保存上下文,如果它需要引用存储库,它将在尚未创建存储库时创建它,并在其保存的上下文中传递

本文还介绍了他们如何将常规MVC控制器实现转换为使用工作单元模式。


UnitOfWork用于管理原子操作

Repository封装了数据存储中持久化的对象集以及对其执行的操作

如果您传递了上下文或UnitOfWork,那么您没有实现UnitOfWork+存储库模式,这将导致您从UnitOfWork中退出其职责。你不需要它


如果您只通过DbSet,则正确实现。实际上您不需要更多。

这基本上就是我所做的,添加了一个IUnitOfWork接口,但就单元测试而言,您认为如何?你真的要对你的存储库和工作单元进行单元测试吗?在考虑了一点之后,我想知道你是如何将实现抽象到调用代码中的,并且仍然将上下文从IoC容器中提取到repo中的?你有代码样本吗?谢谢顺便说一句,我刚刚读了你的MVC3.0书,很棒的书@Sam-系统中的控制器或其他组件将仅与接口定义(如IUnitOfWork)一起工作。只有您的容器才知道IUnitOfWork映射到UnitOfWork,并且通常配置到容器中,也就是说,使用StructureMap,您通常会有一段启动代码,上面写着x.For()!谢谢你的链接。糟糕的文章!他们确实在unitofwork类中创建了上下文和存储库,而不是使用di工具注入这两者。