如何创建ORM独立的通用存储库?

时间:2014-06-08 08:59:05

标签: c# entity-framework repository

这是我的通用基础存储库(其中的一部分) - 使用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更改为其他东西(理论上非常不可能)?

谢谢

2 个答案:

答案 0 :(得分:2)

不同的ORM具有非常不同的API。 EF需要DbContext,NHibernate需要Session,Dapper需要普通的DbConnection,MongoDB需要MongoDatabase。因此,不应该有一些基类适合不同ORM的任何可能的API。如果您需要最佳性能,甚至可以从ORM切换到普通ADO。实际上有时甚至可以将对象存储在内存中。

你应该拥有 interfaces ,它将针对不同的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 。如果我需要不同的实现,我只需切换持久性程序集。

答案 1 :(得分:0)

对于这个问题,我有一个非常明确的解决方案。您应该分离PersonRepository实现。结果,您需要独立于ORM的IPersonRepository接口。而且,您可以从此接口继承任何ORM特定的实现。

<nav>
  <ul>
    <li>
      <a class="navbar-brand" href="#">Navbar Brand</a>
    </li>
    <li>
      <a href="#">Home</a>
    </li>
    <li>
      <a href="#">About</a>
    </li>
    <li>
      <a href="#">services</a>
    </li>
  </ul>
</nav>


<div class="title-image">
  <img src="https://images.unsplash.com/photo-1599546824091-f49550ce8cbc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60">
</div>
public interface IRepository<T>
{
    public TEntity Add(TEntity entity);
    //get T,
    //...
}

您应将通用IRepository和通用EfRepositoryBase保留在 Common 名称空间中。

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,
  //...
}
public interface IPersonRepository : IRepository<Person>
{
}
public interface EfPersonRepository : EfRepositoryBase<Person, MyDbContext> IRepository<Person>
{
}

您应该将PersonRepository,EfPersonRepository和MyOrmPersonRepository保留在 Repositories 名称空间之内。

public interface MyOrmPersonRepository : IRepository<Person>
{
    public Person Add(Person p)
    {
        // MyOrm specific codes...
    }

    //get Person,
    //...
}
public class PersonService
{
    IPersonRepository _personRepository;
    
    public Client(IPersonRepository personRepository)
    {
        _personRepository = personRepository;
    }

    public void AddPerson(Person p)
    {
        //business, validations, logging etc.
        //...
        _personRepository.Add(p);
    }
}

您可以检查此project以获得有关此建筑设计的更多信息