多数据提供者/ORM上的存储库模式

本文关键字:存储 模式 提供者 ORM 多数据 | 更新日期: 2023-09-27 18:01:27

假设我有以下数据模型:

public class Account
{
   public string Username { get; set; }
   public string Password { get; set; }
}
public class Configuration
{
   public string Key { get; set; }
   public string Value { get; set; }
}

目前,它们每个都有自己的数据访问存储库,并使用实体框架作为其工作单元/DbContext。我计划将配置部分从实体框架中拉出来,并使用Redis或Memcached作为其数据访问。我甚至可能要切换EF到NHibernate或没有ORM,我可能会切换数据库到MongoDB或CouchDB。

做这件事的好方法是什么?对我的业务逻辑中那些底层的东西一无所知?使用什么样的模式?为这样的变化而设计是可能的还是糟糕的?

谢谢:)

多数据提供者/ORM上的存储库模式

正如上一篇文章所述,你应该走"界面之路"。我个人不直接实现每个表单的存储库,但我使用了一点变化。用你的例子…

public interface IAccountRepository
{
  Account Get(int id);
  void Delete(int id);
  ...other method...
}

然后创建存储库

public class AccountRepository : IAccountRepository
{
   private readonly IUnitofWork unitofWork;
   public AccountRepository(IUnitofWork unitofWork)
   {
      this.unitofWork = unitofWork;
   }
   //Implement interface method
   public Account Get(int id)
   {
      //some logic or just the call to the unit of work
      return unitofWork.Get(id);
   }
}

我对这个解决方案很满意,因为我最终只有一个存储库,90%的时间使用linq进行查询,所以我不必为每个工作单元编写sql,每次我必须编写带有分页的"GetAllProducts"时,我不必为每个工作单元编写相同的代码(和测试),而只需为我的存储库编写代码。这显然是一个简单的例子,我希望你们能理解。您可以创建一个RepositoryBase来实现使用linq的Find()或Query()方法。然后用你的温莎城堡或ninject或任何你可以注入你喜欢的工作单元。希望能有所帮助。

更新:我的UnitofWorkBase实现nhibernate的示例是类似的:

public class NHUnitofWork<T> : IUnitofWork<T> where T : EntityBase
{
protected INHSessionBuilder SessionBuilder { get; private set; }
public NHPersistorBase(INHSessionBuilder sessionBuilder)
{
  SessionBuilder = sessionBuilder;
}
public T Get(int id)
{
  T result = null;
  ISession session = SessionBuilder.GetSession();
  using (ITransaction transaction = session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
  {
    try
    {
      result = (T)session.Get(typeof(T), id);
      transaction.Commit();
    }
    finally
    {
      if (transaction.IsActive)
        transaction.Rollback();
    }
  }
  return result;
}
public IQueryable<T> Find()
{
  return SessionBuilder.GetSession().Query<T>();
}

}

使用一个接口

public class IAccountRespository
{
   public Account LoadAccountByUsername(String Username);
   public void DeleteAccont(Account a);
   public void SaveAccont(Account a);
   .
   .
   .
   ...more methods
}

然后在每个数据访问对象(ef, mongodb等)上实现这个接口。

在您的业务逻辑代码中,您只使用接口而不是实际的对象。

我使用工厂模式来创建数据访问对象,但是您可以使用任何IoC模式。