将数据上下文从工作单元传递到存储库

时间:2011-10-23 18:52:54

标签: c# repository unit-of-work

我一直在使用存储库进行数据访问已有一段时间了,但从未成功实现类似于工作单元模式的任何内容。我已经开始使用RavenDB和ASP.NET MVC进行自我教育的新项目(理论上这些细节应该是微不足道的),我希望建立一个包装业务交易的好方法( web)要求)在他们自己的工作单位,但我有一些困难。

以下代码段是我喜欢的内容:

public class UserService : IUserService
    {
        private readonly IRepository<User> _userRepository;
        private readonly IRepository<Role> _roleRepository;

        public UserService(
               IRepository<User> userRepository, 
               IRepository<Role> roleRepository)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
        }

        public void Register(User user)
        {
            using (var session = UnitOfWork.Begin())
            {
                _userRepository.Create(user);
                _roleRepository.AddToRole(user, Role.Public);
                session.Commit();
            }
        }
    }

我对工作单元界面的第一次尝试看起来像这样:

 public interface IUnitOfWork : IDisposable
    {
        void Commit();
    }

    public class UnitOfWork : IUnitOfWork
    {
        private readonly IDocumentSession _session;

        public UnitOfWork(IDocumentStore documentStore)
        {
            _session = documentStore.OpenSession("http://from:config");
        }

        public void Commit()
        {
            _session.SaveChanges();
        }

        public static IUnitOfWork Begin()
        {
            return IoC.GetInstance<IUnitOfWork>();
        }

        public void Dispose()
        {
            _session.Dispose();
        }
  }

我遇到的是存储库对数据库会话的访问。正如我所提到的,我想将商业交易包装在自己的单位中;我也不热衷于将会话/上下文传递给每个方法,而我见过的大多数其他解决方案都使用静态方法和/或存储在Web会话中。所有这些让我有点不舒服;在整个工作单元概念中,我是否缺少一些关键点?

2 个答案:

答案 0 :(得分:1)

我不喜欢TransactionScope的概念,还有进一步的研究和进展。讨论让我相信我想做的事情根本不可行。

最后,UnitOfWork上下文中的存储库需要(明确地)了解UnitOfWork。我还没有确定要走哪条路,但我会做类似以下的事情:

using (var session = UnitOfWork.Begin())
            {
                _userRepository.Use(session).Create(user);
                _roleRepository.Use(session).AddToRole(user, Role.Public);
                session.Commit();
            }

using (var session = UnitOfWork.Begin())
            {
                session.Get<IUserRepository>().Create(user);
                session.Get<IRoleRepository>().AddToRole(user, Role.Public);
                session.Commit();
            }

我对这两种方法都不是很疯狂;在我收到更好的建议之前,我会将此标记为答案。

答案 1 :(得分:0)

Julia Lerman有一些使用实体框架的工作单元的很好的例子。

在实体框架中,它在上下文中得到支持,因此很容易实现一个工作单元。 我会看到的主要问题是你如何管理订单。 示例:表A和表B

表B具有表A的外键。 您的工作单元必须知道订购,否则会出错。 我会选择像Nhibernate或EF这样的OR / M. 它应该变得更容易。