我一直在查看关于工作单元和存储库模式主题的代码审查,并意识到我的实现似乎提供了非常类似的功能,但采用的是反向类顺序/层次结构。(想不出更好的方式来形容它了,对不起)
我在下面添加了我的代码。我希望您能就我的实现提供任何关于正确性、效率和任何建议的反馈。
UnitOfWork.cs - UnitOfWork + IUnitOfWork
public class UnitOfWork : IUnitOfWork
{
PropertyInfoEntities _context = null;
public IXXXXXRepository XXXXXRepository { get; set; }
public IPersonRepository PersonRepository { get; set; }
public IPersonLoginRepository PersonLoginRepository { get; set; }
public IPropertyApplicationRepository PropertyApplicationRepository { get; set; }
public ISaleTypeRepository SaleTypeRepository { get; set; }
public IStatusRepository StatusRepository { get; set; }
public ITownRepository TownRepository { get; set; }
public ITypeRepository TypeRepository { get; set; }
public UnitOfWork() : this(new PropertyInfoEntities()) { }
public UnitOfWork(PropertyInfoEntities context)
{
_context = context;
InitRepositories();
}
private void InitRepositories()
{
XXXXXRepository = new XXXXXRepository(_context);
PersonRepository = new PersonRepository(_context);
PersonLoginRepository = new PersonLoginRepository(_context);
PropertyApplicationRepository = new PropertyApplicationRepository(_context);
SaleTypeRepository = new SaleTypeRepository(_context);
StatusRepository = new StatusRepository(_context);
TownRepository = new TownRepository(_context);
TypeRepository = new TypeRepository(_context);
}
public void Save()
{
_context.SaveChanges();
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing == true)
{
_context = null;
}
}
~UnitOfWork()
{
Dispose(false);
}
#endregion
}
public interface IUnitOfWork : IDisposable
{
IXXXXXRepository XXXXXRepository { get; set; }
IPersonRepository PersonRepository { get; set; }
IPersonLoginRepository PersonLoginRepository { get; set; }
IPropertyApplicationRepository PropertyApplicationRepository { get; set; }
ISaleTypeRepository SaleTypeRepository { get; set; }
IStatusRepository StatusRepository { get; set; }
ITownRepository TownRepository { get; set; }
ITypeRepository TypeRepository { get; set; }
void Save();
}XXXXXRepository.cs - XXXXXRepository + IXXXXXRepository
public class XXXXXRepository : IXXXXXRepository
{
PropertyInfoEntities _context = null;
public XXXXXRepository() : this(new PropertyInfoEntities()) { }
public XXXXXRepository(PropertyInfoEntities context)
{
_context = context;
}
public IQueryable<XXXXX> All
{
get { return _context.XXXXXs; }
}
public IQueryable<XXXXX> AllIncluding(params Expression<Func<XXXXX, object>>[] includeProperties)
{
IQueryable<XXXXX> query = _context.XXXXXs;
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
return query;
}
public XXXXX Find(int id)
{
return _context.XXXXXs.Find(id);
}
public XXXXX FindNT(int id)
{
return _context.XXXXXs.AsNoTracking().Single(f => f.ID == id);
}
public void InsertOrUpdate(XXXXX XXXXX)
{
if (XXXXX.ID == default(int))
{
// New entity
_context.XXXXXs.Add(XXXXX);
}
else
{
// Existing entity
_context.Entry(XXXXX).State = System.Data.Entity.EntityState.Modified;
}
}
public void Delete(int id)
{
var XXXXX = _context.XXXXXs.Find(id);
_context.XXXXXs.Remove(XXXXX);
}
public void Save()
{
_context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
public interface IXXXXXRepository : IDisposable
{
IQueryable<XXXXX> All { get; }
IQueryable<XXXXX> AllIncluding(params Expression<Func<XXXXX, object>>[] includeProperties);
XXXXX Find(int id);
XXXXX FindNT(int id);
void InsertOrUpdate(XXXXX XXXXX);
void Delete(int id);
void Save();
}如果我的实现不是不正确的,我计划将UoW存储库属性更改为自实例化字段以提高效率,并使用BaseController加载到控制器中。然而,阅读一些其他代码评审问题已经使我的实现感到错误。
编辑(4年后):回顾过去,我的实现是可怕的;主要是因为InitRepositories()方法被UoW构造函数调用。这意味着对于UoW的每一个实例化,它都将实例化每个存储库,而不管它们是否可以被使用。除此之外,实现也不算太糟糕,尽管对大多数其他人来说,它确实是按相反顺序工作的。如果您想在UoW中显式地保存存储库,您应该将它们实现为(请原谅我的术语)惰性地自实例化属性,如这里。现在,我更喜欢使用URF.NET并根据需要定制它。
发布于 2014-04-14 20:32:44
我明白你所说的“颠倒”:

相对于:

至少对我来说,这是有意义的--我认为UoW/Repository模式(每个人似乎都有自己的看法,嗯?),实体框架的DbContext是一个工作单元,而IDbSet<TEntity>是一个存储库。
因此,我倾向于同意让工作单元依赖于存储库,而不是相反。当我们继承DbContext时,我们公开了IDbSet<TEntity>属性,这正是您在这里得到的。
问题是,如果DbContext是一个工作单元,而IDbSet<TEntity>是一个存储库.那么,还有什么需要用只会增加复杂性的基础结构代码来包装呢?
您并没有展示UoW实现是如何在控制器中使用的,但是如果您直接使用它,那么您正在使用IQueryable<T>,并且您并没有真正包装任何东西,EF和Linq- then正在从您对每个存储库调用的每一次使用中流血,使得额外的抽象不是完全抽象的。
我还没有看到一个带有EF的UoW+Repository实现,它将向我展示直接在控制器中使用DbContext的真正好处(或者更恰当地说,在一个专用的、可测试的服务类中)。
相反,我倾向于这样做:
public Interface IUnitOfWork
{
IDbSet<TEntity> Set<TEntity>();
void Save();
}
public class SomeContext : DbContext, IUnitOfWork
{
public void Save() // base method returns an int that I don't want
{
base.SaveChanges(); // qualifier "base" is redundant, specified for readability
}
}然后,我可以注入一个IUnitOfWork并为任何实体类型获取一个IDbSet<TEntity>,并使用该接口执行EF为我准备好的一切;IUnitOfWork只是启用了模拟,因此我可以设置它以在调用Set<Person>()时返回一个模拟IDbSet<Person>。留着。它。很简单。
https://codereview.stackexchange.com/questions/47144
复制相似问题