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

发布于 2024-11-19 04:38:16 字数 508 浏览 6 评论 0原文

假设我有以下数据模型:

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。

这样做的好方法是什么?对我的业务逻辑中所有底层的东西一无所知?使用什么样的模式?针对这样的变化进行设计是否可能,或者只是一件坏事?

谢谢 :)

Let just say I have the following data models:

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; }
}

For now, each of them has their own repository for data access, and uses entity framework as its unit of work/DbContext. I'm planning to pull out the Configuration part out of the entity frame and use Redis or Memcached as its data access. I might even to switch the EF to NHibernate or no ORM at all, and I might switch the database to MongoDB or CouchDB.

What is the good way to do this? To be ignorant of all those lower layer stuff in my business logic? What kind of pattern to use? Is it possible or is it just bad things to design for changes like this?

Thanks :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

掩饰不了的爱 2024-11-26 04:38:16

正如上一篇文章所述,您应该走“界面之路”。
我个人不会直接为每个 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() 方法。
然后用你的 Castle Windsor 或 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>();
}

}

As stated in the previous post, you should go the "way of the Interface".
I personally do not implement directly the repository for each orm but I use a little variation.
Using your example...

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

then you create your repository

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);
   }
}

I am happy with this solution because I end up with only one repository that 90% of the time use linq to query so I don't have to write the sql for each unit of work and every time I have to write a "GetAllProducts" with paging I do not have to write the same code (and tests) for every unit of work, but only for my repository. This is a simple example obviously so I hope you get the idea.
You can make a RepositoryBase that implement a method Find() or Query() which use linq.
Then with your Castle Windsor or ninject or whatever you can inject the unit of work you prefer. Hope it helps.

Update:
a sample of my UnitofWorkBase that implement nhibernate is something similar:

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>();
}

}

等待我真够勒 2024-11-26 04:38:16

使用接口。

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

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

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

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

Use an interface.

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

then you implement this interface on every data access object (ef,mongdb, etc. etc).

In your business logic code you use just the interface and not the acual object.

i use the factory pattern to create the data access objects, but you can use every IoC pattern.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文