首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVC 5和EF 6-仓库和工作模式单元

MVC 5和EF 6-仓库和工作模式单元
EN

Code Review用户
提问于 2014-04-14 14:01:12
回答 1查看 11.7K关注 0票数 8

我一直在查看关于工作单元和存储库模式主题的代码审查,并意识到我的实现似乎提供了非常类似的功能,但采用的是反向类顺序/层次结构。(想不出更好的方式来形容它了,对不起)

这是一个问题,我觉得我的类似,但在反向。

我在下面添加了我的代码。我希望您能就我的实现提供任何关于正确性、效率和任何建议的反馈。

UnitOfWork.cs - UnitOfWork + IUnitOfWork

代码语言:javascript
复制
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

代码语言:javascript
复制
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并根据需要定制它。

EN

回答 1

Code Review用户

回答已采纳

发布于 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的真正好处(或者更恰当地说,在一个专用的、可测试的服务类中)。

相反,我倾向于这样做:

代码语言:javascript
复制
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>。留着。它。很简单。

票数 12
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/47144

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档