3

我将在我的数据访问层中使用存储库和 UnitOfwork 来执行此操作,看看一个联系人聚合根

 public interface IAggregateRoot
    {
    }

这是我的通用存储库接口:

 public interface IRepository<T>
        {
            IEnumerable<T> GetAll();
            T FindBy(params Object[] keyValues);
            void Add(T entity);
            void Update(T entity);
            void Delete(T entity);

        }

和我在模型中的 POCO 联系课程

 public class Contact :IAggregateRoot
        {
            public Guid Id { get; set; }
            public string Name { get; set; }
            public string Email { get; set; }
            public string Title { get; set; }
            public string Body { get; set; }
            public DateTime CreationTime { get; set; }
        }

这是我的 IContactRepository 继承自 IRepository 并且可能有它自己的方法

 public interface IContactRepository : IRepository<Contact>
        {
        }

现在我已经像这样在 IUitOfWork 和 UnitOfwork 中完成了

public interface IUnitOfWork 
    {
        IRepository<Contact> ContactRepository { get; }
    }

public class UnitOfWork : IUnitOfWork
    {
        private readonly StatosContext _statosContext = new StatosContext();
        private IRepository<Contact> _contactUsRepository;

 public IRepository<Contact> ContactRepository
        {
            get { return _contactUsRepository ?? (_contactUsRepository = new Repository<Contact>(_statosContext)); }
        }
}

还有关于我的存储库

public class Repository<T> : IRepository<T> where T : class, IAggregateRoot
    {
       //implementing methods 
    }

我可以通过在 Service 中使用 UnitOfwork 访问存储库来执行所有 CRUD 操作,例如:

_unitOfWork.ContactRepository.Add(contact);
            _unitOfWork.SaveChanges();

但我想这样做

_

ContactRepository.Add(contact);
            _unitOfWork.SaveChanges();

(通过_unitOfWork.ContactRepository 的_ContactRepository No 获取CRUD 和通用方法) 因为我想获取一些特定查询的ContactRepository 方法,有人帮忙吗??

4

3 回答 3

11

这不是您问题的直接答案,但它可能会简化一些事情并减少重复。

当您使用 EntityFramework Power Tools 对 Code First 进行逆向工程(或通常仅使用 Code First)时,您最终会得到DbContext一个用作 UoW 和存储库的类,例如:

public partial class YourDbContext : DbContext
{
    public DbSet<Contact> Contacts {get; set;}
}

现在,如果你想让事情变得可测试,有一个简单的方法:引入一个非常薄的接口:

public interface IDbContext
{
    IDbSet<T> EntitySet<T>() where T : class;
    int SaveChanges();
    //you can reveal more methods from the original DbContext, like `GetValidationErrors` method or whatever you really need.
}

然后用部分类的第二部分制作另一个文件:

public partial class YourDbContext : IDbContext
{
     public IDbSet<T> EntitySet<T>() where T : class
     {
         return Set<T>();
     }
}

达达!IDbContext现在您可以通过YourDbContext备份注入:

//context is an injected IDbContext:
var contact = context.EntitySet<Contact>().Single(x => x.Id == 2);    
contact.Name = "Updated name";
context.EntitySet<Contact>().Add(new Contact { Name = "Brand new" });
context.SaveChanges();

现在,如果您想控制上下文的处理,那么您必须编写自己的(gaspIDbContextFactory(通用与否,取决于您的需要)并注入该工厂。

无需编写自己的Find,AddUpdate现在的方法DbContext就可以适当地处理它,引入显式事务更容易,并且一切都很好地隐藏在接口 ( IDbContext, IDbSet) 后面。

顺便说一句,这IDbContextFactory将等同于 NHibernate 的ISessionFactoryIDbContext- ISession。我希望 EF 也能开箱即用。

于 2013-05-09T18:04:09.833 回答
2

我同意 Doctor 的观点,DbContext 已经是一个 UnitOfWork,在它之上添加另一个 UoW 抽象通常是多余的,除非您认为您将来很有可能会切换数据库技术。

但是,我不同意将 DbSet 视为存储库,因为这会将您的查询与使用它们的方法紧密结合。如果您需要更改查询,则必须在使用它的任何地方进行。

我更喜欢使用独立的存储库(或服务接口,它们提供类似的功能)或使用更多的 CQRS 系统进行命令/查询分离,即使用查询对象。

于 2013-05-09T18:32:46.973 回答
0

在 UnitOfWork 类中,您需要实现 DBContext 或 ObjectContext。

UnitOfWork 隔离所有交易,无论系统如何。EF 仅用于数据库连接。即使您的系统仅使用 DB,最好保留一个单独的 UnitOfWork 类以供将来扩展。

在工作单元 Commit() 中,您可以调用内部实现的 DBContext.SaveChanges()。

所有在 unitofwork 中声明的存储库都可以访问此 DBcontext。因此存储库从 DBcontext 添加或删除,并且 unitOfwork 提交它。

当您有跨越不同存储的场景时,例如:云 Blob、表存储等。您可以在 UnitofWork 中实现它们,就像您实现 EF 上下文一样。并且一些存储库可以访问表存储和一些 EF 上下文。

提示:实现 ObjectContext 而不是 DBContext 可以让您在缓存场景中占据优势。而且您在扩展框架方面有更多选择。

于 2014-08-04T10:38:46.370 回答