实体框架6,存储库模式和工作单元

时间:2014-11-17 19:21:51

标签: c# entity-framework design-patterns repository-pattern

我正在学习实体框架和一些设计模式,例如存储库模式和工作单元。我写了一个使用这些模式的程序。在这个类中,我有一个DbContext对象,我总是使用这个静态DbContext。在我的应用程序的整个生命周期中,只有一个DbContext对象。我是否正确地使用这种方式,想想是否有很多用户。将是有关数据库连接的任何问题。

UI代码:

UnitOfWork uow = GetUnitOfWork(); //There is only one uow object
uow.EmployeeRepository.Insert(new Employee
{
    Name = name,
    Surname = surname
});

GetUnitOfWork代码:

private static UnitOfWork _uow;
public static UnitOfWork GetUnitOfWork()
{
    return _uow ?? (_uow = new UnitOfWork());
}

UnitOfWork代码:

public class UnitOfWork : IDisposable
{
    private static FollowerEntities _context;
    private DbContextTransaction _transaction;

    //repositories
    private EmployeeRepository _employeeRepository;


    public UnitOfWork()
    {
        _context = new FollowerEntities();
    }

    public EmployeeRepository EmployeeRepository
    {
        get { return _employeeRepository ?? (_employeeRepository = new EmployeeRepository(_context)); }
    }

    public void Save()
    {
        try
        {
            _transaction = _context.Database.BeginTransaction();
            _context.SaveChanges();
            _transaction.Commit();
        }
        catch
        {
            _transaction.Rollback();
            throw;
        }
    }

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

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_context != null)
            {
                _context.Dispose();
                _context = null;
            }
        }
    }
}

员工存储库

public class EmployeeRepository : GenericRepository<Employee>
{
    public EmployeeRepository(FollowerEntities entities)
        : base(entities)
    {

    }
}

通用存储库

public class GenericRepository<T> where T : class
{
    private FollowerEntities _entities;


    private DbSet<T> table = null;

    public GenericRepository()
    {

    }

    public GenericRepository(FollowerEntities entities)
    {
        this._entities = entities;
        table = _entities.Set<T>();
    }

    public IEnumerable<T> SelectAll()
    {
        return table.ToList();
    }

    public T SelvectById(object id)
    {
        return table.Find(id);
    }

    public void Insert(T obj)
    {
        table.Add(obj);
    }

    public void Update(T obj)
    {
        table.Attach(obj);
        _entities.Entry(obj).State = EntityState.Modified;
    }

    public void Delete(object id)
    {
        T existing = table.Find(id);
        table.Remove(existing);
    }
}

1 个答案:

答案 0 :(得分:4)

private static UnitOfWork _uow;
public static UnitOfWork GetUnitOfWork()
{
    return _uow ?? (_uow = new UnitOfWork());
}

虽然技术上是正确的,但这并不像你想象的那样有用。您将API限制为UoW的单个实例。考虑像ASP.NET这样的共享场景,这种方法可能不会像您想象的那样频繁使用。我建议删除它。

public UnitOfWork()
{
    _context = new FollowerEntities();
}

这会不必要地将上下文生命周期与UoW生命周期联系起来。相反,将它们分开:

public UnitOfWork( FollowerEntities context )
{
    _context = context;
}

这样,可以使用其他生命周期管理方法(可能是IoC容器)。

_transaction = _context.Database.BeginTransaction();
_context.SaveChanges();
_transaction.Commit();

您确定应该始终将保存包装在交易中吗?如果同一连接上存在另一个事务并且您想重用它,该怎么办?

最大的问题 - UoW和存储库都不是抽象的(带接口)。这意味着客户端仍然与唯一的实现耦合。您刚刚创建了一个包装的实体框架,但您无法从中受益,例如,您无法在不重写的情况下切换到另一个实现。除了锻炼之外,我没有看到任何坚实的观点。