Domain driven design 我们都在寻找相同的假设吗?
我一直在试图找到一种编写通用存储库的方法,该存储库可用于各种数据存储:Domain driven design 我们都在寻找相同的假设吗?,domain-driven-design,design-patterns,irepository,Domain Driven Design,Design Patterns,Irepository,我一直在试图找到一种编写通用存储库的方法,该存储库可用于各种数据存储: public interface IRepository { IQueryable<T> GetAll<T>(); void Save<T>(T item); void Delete<T>(T item); } public class MemoryRepository : IRepository {...} public class SqlReposi
public interface IRepository
{
IQueryable<T> GetAll<T>();
void Save<T>(T item);
void Delete<T>(T item);
}
public class MemoryRepository : IRepository {...}
public class SqlRepository : IRepository {...}
公共接口IRepository
{
IQueryable GetAll();
作废保存(T项);
作废删除(T项);
}
公共类MemoryRepository:IRepository{…}
公共类SqlRepository:IRepository{…}
我希望在每个域中使用相同的POCO域类。我还考虑采用类似的方法,每个域类都有自己的存储库:
public interface IRepository<T>
{
IQueryable<T> GetAll();
void Save(T item);
void Delete(T item);
}
public class MemoryCustomerRepository : IRepository {...}
public class SqlCustomerRepository : IRepository {...}
公共接口IRepository
{
IQueryable GetAll();
作废保存(T项);
作废删除(T项);
}
公共类MemoryCustomerRepository:IRepository{…}
公共类SqlCustomerRepository:IRepository{…}
我的问题是:1)第一种方法是否可行?2) 第二种方法有什么好处吗
XmlWriter
/XmlReader
。您可以使用这种方法来简化单元测试,尽管我认为现在我们有更好的OSS工具来实现这一点SelectByLastName
或DeleteFromParent
)。正因为如此,我没有必要像您所建议的那样实现单独的存储库——我们的具体映射器以数据库为目标。为了执行单元测试,我使用它并创建内存中的存储库,这些存储库可以像memory*存储库那样运行。对于一个非常可测试的方法来说,它的实现和管理类更少,总体工作也更少。对于跨单元测试共享的数据,我为每个域类使用一个生成器模式,该域类具有WithXXX
方法和AsSomeProfile
方法(AsSomeProfile
仅返回一个带有预配置测试数据的生成器实例)// Moq mocking the concrete PersonMapper through the IPersonMapper interface
var personMock = new Mock<IPersonMapper>(MockBehavior.Strict);
personMock.Expect(pm => pm.Select(It.IsAny<int>())).Returns(
new PersonBuilder().AsMike().Build()
);
// StructureMap's ObjectFactory
ObjectFactory.Inject(personMock.Object);
// now anywhere in my actual code where an IPersonMapper instance is requested from
// ObjectFactory, Moq will satisfy the requirement and return a Person instance
// set with the PersonBuilder's Mike profile unit test data
//Moq通过ipersonapper接口模拟具体的personapper
var personMock=newmock(MockBehavior.Strict);
Expect(pm=>pm.Select(It.IsAny())。返回(
新建PersonBuilder().AsMike().Build()
);
//StructureMap的ObjectFactory
ObjectFactory.Inject(personMock.Object);
//现在,在我的实际代码中,任何一个请求IPersonMapper实例的地方
//ObjectFactory、Moq将满足要求并返回一个Person实例
//使用PersonBuilder的Mike profile单元测试数据进行设置
事实上,现在人们普遍认为域存储库不应该是通用的。存储库应该说明在持久化或检索实体时可以执行的操作
有些存储库是只读的,有些是只插入的(没有更新,没有删除),有些只有特定的查找
使用GetAll返回IQueryable,查询逻辑将泄漏到代码中,可能泄漏到应用程序层
但使用您提供的接口封装Linq表
对象仍然很有趣,这样您就可以用内存中的实现来代替它进行测试
因此,我建议称之为ITable
,为它提供与linq表
对象相同的接口,并在特定域存储库中使用它(而不是替代)
然后,您可以通过使用内存ITable
实现在内存中使用特定的存储库
* Supports all CRUD methods ( Create, Retrieve, Update, Delete )
* Supports aggregate methods Min, Max, Sum, Avg, Count
* Supports Find methods using ICriteria<T>
* Supports Distinct, and GroupBy
* Supports interface IRepository<T> so you can use an In-Memory table for unit-testing
* Supports versioning of your entities
* Supports paging, eg. Get(page, pageSize)
* Supports audit fields ( CreateUser, CreatedDate, UpdateDate etc )
* Supports the use of Mapper<T> so you can map any table record to some entity
* Supports creating entities only if it isn't there already, by checking for field values.
在内存中实现ITable
的最简单方法是使用List
并使用.AsQueryable()扩展方法获得IQueryable
接口
public class InMemoryTable<T> : ITable<T>
{
private List<T> list;
private IQueryable<T> queryable;
public InMemoryTable<T>(List<T> list)
{
this.list = list;
this.queryable = list.AsQueryable();
}
public void Add(T entity) { list.Add(entity); }
public void Remove(T entity) { list.Remove(entity); }
public IEnumerator<T> GetEnumerator() { return list.GetEnumerator(); }
public Type ElementType { get { return queryable.ElementType; } }
public IQueryProvider Provider { get { return queryable.Provider; } }
...
}
InMemoryTable中的公共类:ITable
{
私人名单;
私有的可查询的;
公共InMemoryTable(列表)
{
this.list=列表;
this.queryable=list.AsQueryable();
}
公共void Add(T实体){list.Add(实体);}
公共无效删除(T实体){list.Remove(实体);}
公共IEnumerator GetEnumerator(){返回列表。GetEnumerator();}
公共类型ElementType{get{return queryable.ElementType;}}
公共IQueryProvider提供程序{get{return queryable.Provider;}}
...
}
您可以独立于数据库进行测试,但是使用真正的特定存储库,可以提供更多的领域洞察力。这有点晚了。。。但请看一下codeplex上的IRepository实现。它有一个非常好的功能集 关于您的问题,我看到很多人使用诸如GetAllProducts()、GetAllEmployees()之类的方法 在他们的存储库实现中。这是多余的,不允许您的存储库是通用的。 您只需要GetAll()或All()。不过,上面提供的解决方案确实解决了命名问题 这是从CommonLibrary.NET联机文档中获取的: 0.9.4 Beta 2有一个强大的存储库实现
* Supports all CRUD methods ( Create, Retrieve, Update, Delete )
* Supports aggregate methods Min, Max, Sum, Avg, Count
* Supports Find methods using ICriteria<T>
* Supports Distinct, and GroupBy
* Supports interface IRepository<T> so you can use an In-Memory table for unit-testing
* Supports versioning of your entities
* Supports paging, eg. Get(page, pageSize)
* Supports audit fields ( CreateUser, CreatedDate, UpdateDate etc )
* Supports the use of Mapper<T> so you can map any table record to some entity
* Supports creating entities only if it isn't there already, by checking for field values.
*支持所有CRUD方法(创建、检索、更新、删除)
*支持聚合方法Min、Max、Sum、Avg、Count
*支持使用ICriteria查找方法
*支持Distinct和GroupBy
*支持接口IRepository,因此您可以使用内存中的表进行单元测试
*支持实体的版本控制
*支持分页,例如Get(page,pageSize)
*支持审核字段(CreateUser、CreateDate、UpdateDate等)
*支持使用映射器,因此您可以将任何表记录映射到某个实体
*通过检查字段值,仅当实体不存在时才支持创建实体。