微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 通用存储库和事务

我在MVC应用程序中实现了我的第一个Generic存储库.工作正常,但如何将存储库放在事务范围?
public interface IRepository<TEntity> where TEntity : class
    {
        List<TEntity> FetchAll();
        IQueryable<TEntity> Query { get; }
        void Add(TEntity entity);
        void Delete(TEntity entity);
        void Save();
    }


    public class Repository<T> : IRepository<T> where T : class
    {
        private readonly DataContext _db;

        public Repository(DataContext db)
        {
            _db = db;
        }

        #region IRepository<T> Members

        public IQueryable<T> Query
        {
            get { return _db.GetTable<T>(); }
        }

        public List<T> FetchAll()
        {
            return Query.ToList();
        }

        public void Add(T entity)
        {
            _db.GetTable<T>().InsertOnSubmit(entity);
        }

        public void Delete(T entity)
        {
            _db.GetTable<T>().DeleteOnSubmit(entity);
        }

        public void Save()
        {
            _db.SubmitChanges();
        }

        #endregion
    }

        private void RegisterDependencyResolver()
        {
            var kernel = new StandardKernel();         
            var connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            kernel.Bind(typeof(DataContext)).ToMethod(context => new DataContext(connectionString));
            kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));            
            DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
        }


    public class AdminController : Controller
    {

        private readonly IRepository<User> _userRepository;
        private readonly IRepository<Order> _orderRepository;

public AdminController(IRepository<User> userRepository,IRepository<Order> orderRepository)
        {
            _userRepository = userRepository;
            _orderRepository = orderRepository;
        }






 public ActionResult InsertUser(Userviewmodel model)
        {

//Skip Code
//Do not commit data to database if _orderRepository is Failed to save data
       _userRepository.Add(user);
            _userRepository.Save();


//Skip Code
      _orderRepository.Add(order);
            _orderRepository.Save();

}


}

在InsertUser操作中使用Transaction作用域包装存储库代码的最佳方法是什么?

解决方法

在这里错过了一个抽象.您应该将所有业务逻辑放在命令处理程序中,并创建一个实现事务行为的命令处理程序装饰器. This article描述了如何做到这一点,但简而言之:

>定义ICommandHandler< TCommand>接口:

public interface ICommandHandler<TCommand>
{
    void Handle(TCommand command);
}

>创建定义业务操作合同的命令.命令只是DTOs(只有数据,没有行为).例如:

public class ShipOrderCommand
{
    public int OrderId { get; set; }

    public ShippingInfo Info { get; set; }
}

>实现将包含这些命令的业务逻辑/行为的命令处理程序:

public class ShipOrderCommandHandler 
    : ICommandHandler<ShipOrderCommand>
{
    private readonly IRepository<Order> repository;

    public ShipOrderCommandHandler(
        IRepository<Order> repository)
    {
        this.repository = repository;
    }

    public void Handle(ShipOrderCommand command)
    {
        // do some useful stuf with the command and repository.
    }
}

>让你的MVC控制器依赖于ICommandHandler< T>抽象:

public ShipOrderController : Controller
{
    private readonly ICommandHandler<ShipOrderCommand> handler;

    public ShipOrderController(
        ICommandHandler<ShipOrderCommand> handler)
    {
        this.handler = handler;
    }

    public void Ship(int orderId,ShippingInfo info)
    {
        this.handler.Handle(new ShipOrderCommand
        {
            OrderId = orderId,Info = info
        });
    }
}

>定义实现事务逻辑的通用装饰器:

public TransactionalCommandHandlerDecorator<TCommand>
    : ICommandHandler<TCommand>
{
    private ICommandHandler<TCommand> decoratedHandler;

    public TransactionalCommandHandlerDecorator(
        ICommandHandler<TCommand> decoratedHandler)
    {
        this.decoratedHandler = decoratedHandler;
    }

    public void Handle(TCommand command)
    {
        using (var scope = new TransactionScope())
        {
            this.decoratedHandler.Handle(command);
            scope.Complete();
        }
    }
}

>确保每个ShipOrderCommandHandler都使用TransactionalCommandHandlerDecorator进行修饰并注入ShipOrderController.您可以使用您喜欢的DI容器或手动执行此操作:

protected override IController GetControllerInstance(
    RequestContext requestContext,Type controllerType)
{
    if (controllerType == typeof(ShipOrderController))
    {
        return new ShipOrderController(
            new TransactionalCommandHandlerDecorator<ShipOrderCommand>(
                new ShipOrderCommandHandler(
                    new OrderRepository())));
    }

    return base.GetControllerInstance(requestContext,controllerType);
}

有了这个,您就可以在事务中运行所有业务逻辑,而无需业务逻辑了解这一点.

原文地址:https://www.jb51.cc/csharp/243684.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐