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

本文关键字:存储 单元 数据 上下文 工作 | 更新日期: 2023-09-27 18:12:23

我使用存储库进行数据访问已有一段时间了,但从未成功实现过类似于工作单元模式的任何东西。我开始了一个使用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会话中。所有这些都让我有点不舒服;在整个工作单元的概念中,我是不是漏掉了什么关键的东西?

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

我不喜欢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();
            }

这两种方法我都不喜欢;在我收到更好的建议之前,我会把这个标记为答案。

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

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

表B有一个指向表a的外键。你的功单位必须知道如何排序,否则就会出错。我会选择OR/M,比如Nhibernate或EF。这会让事情变得简单很多