如何创建独立于ORM的通用存储库
本文关键字:ORM 存储 独立 何创建 创建 | 更新日期: 2023-09-27 18:07:15
这是我的通用基础存储库(它的一部分)-使用EntityFramework 6(是的,EF6确实有一个通用存储库,但网上有很多相互冲突的意见,是否仍然使用存储库模式,我现在使用存储库)
public class BaseRepository<T> : IBaseRepository<T> where T: class
{
private BlueWhaleEntities _dbContext;
public BlueWhaleEntities DbContext { get; set; }
public BaseRepository(BlueWhaleEntities dbContext )
{
_dbContext = dbContext;
}
//...More Add,Remove Generic Methods
我有一个更具体的PersonRespository
class PersonRepository: BaseRepository<Person>
{
public PersonRepository(BlueWhaleEntities blueWhaleEntities) : base(blueWhaleEntities)
{
//...Add,Remove methods for Person which override Generic repository's methods
}
}
但是看看这个,存储库的一个目的是我可以改变orm ..但是我在构造函数中注入了EntityFramework DataContext,将我绑定到EF。
那么我在构造函数中注入什么,然后我可以在需要的时候将ORM更改为其他东西(非常不可能,但理论上)?
谢谢
不同的orm有非常不同的api。EF需要DbContext, NHibernate需要Session, Dapper需要普通的DbConnection, MongoDB有MongoDatabase。因此,不应该有一些基类来适应不同orm的任何可能的API。如果需要最佳性能,甚至可以从ORM切换到普通ADO。实际上,有时你甚至可以将对象存储在内存中。
你应该拥有的是接口,这些接口将在不同的orm
中实现public interface IRepository<T>
{
T GetById(object id);
void Add(T entity);
// ...
}
public interface IPersonRepository : IRepository<Person>
{
IEnumerable<Person> GetPeopleByDepartment(int id);
}
它们的目的是对应用程序隐藏实现细节。依赖这些接口。创建不同的实现。我通常将存储库实现移动到独立的程序集,其名称类似于Foo.Persistence。EF或Foo.Persistence.NHibernate。如果我需要不同的实现,我只需切换持久性程序集。
对于这个问题,我有一个非常明确的解决方案。您应该分离PersonRepository实现。因此,您需要独立于ORM的IPersonRepository接口。您可以从这个接口继承任何ORM特定的实现。
public interface IRepository<T>
{
public TEntity Add(TEntity entity);
//get T,
//...
}
public interface EFRepositoryBase<TEntity, TContext> : IRepository<TEntity>
{
public TEntity Add(TEntity entity)
{
using var context = new TContext();
var addedEntity = context.Entry(entity);
addedEntity.State = EntityState.Added;
context.SaveChanges();
return entity;
}
//get T,
//...
}
你应该保持通用的IRepository和通用的EfRepositoryBase在像Common命名空间。
public interface IPersonRepository : IRepository<Person>
{
}
public interface EfPersonRepository : EfRepositoryBase<Person, MyDbContext> IRepository<Person>
{
}
public interface MyOrmPersonRepository : IRepository<Person>
{
public Person Add(Person p)
{
// MyOrm specific codes...
}
//get Person,
//...
}
你应该保持PersonRepository, EfPersonRepository和MyOrmPersonRepository在类似的Repositories命名空间。
public class PersonService
{
IPersonRepository _personRepository;
public Client(IPersonRepository personRepository)
{
_personRepository = personRepository;
}
public void AddPerson(Person p)
{
//business, validations, logging etc.
//...
_personRepository.Add(p);
}
}
public class Client
{
//...
void Main()
{
//You should use DI tool in here
PersonService personService = new PersonService(new EfPersonRepository());
//or
PersonService personService2 = new PersonService(new MyOrmPersonRepository());
personService.AddPerson(new Person());
//or
personService2.AddPerson(new Person());
//...
}
}
您可以查看此项目以获取有关此架构设计的更多信息