一次交易中调用多种服务方法 [英] Call multiple service method in one transaction

查看:83
本文介绍了一次交易中调用多种服务方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请原谅我我不擅长EF6.如果我做错了.请帮助我改正它.谢谢.

Forgive me I am not good at EF6. If I make some mistake . Please help me to correct it. Thanks.

首先,我想在服务层中实现业务逻辑,如下所示.

Firstly I want to implement the business logic in my service layer like below.

public class userService
{
    void createWithCommit(User user)
    {
        MyEntityContext db= new MyEntityContext ();
        ...
        db.Users.add(user);//Add a new user entity
        ....
        Work w = new Work();
        ... 
        db.Works.add(w);//Add a new work entity
        db.savechanges();//commit the changes which will insert 2 new record . one is user . another is work.
    }
}

但是在某些服务类中,我想在一个事务中调用其他多个服务方法,如下所示.

But in some service class I want to call multiple others service method in one transaction like below.

class utilService
{
    void update(SomeClass cls)
    {
        using (var tran=new TransactionScope())
        {
          userService userSvr= new userService();
          userSvr.create();//this method already include a savechanges().
          jobService jobSvr= new jobService();
          jobSvr.update();//this method may include another savechanges().
          tran.Complete();//I don't why EF6 doesn't have the Commit method. just has the Complete method.
        }

    }
}

所以我可以在ASP.net MVC控制器中使用它,如下所示.

So I can use it in the ASP.net MVC controller like below.

class SomeController
{
    ActionResult index()
    {
        userService userSvr = new userService();
        userSvr.createWithCommit();

    }

    ActionResult util()
    {
        utilService utilSvr = new utilService ();
        userSvr.update(....);

    }
}

所以您可以看到我的想法是我想在一个事务中包含多种服务方法.并且所包含的每个服务方法都可能包含或可能不包含代码SaveChanges()(这意味着已提交事务.对吗?).

So you can see my idea is I want to include multiple service method into one transaction. and each of the included service methods may or may not include the code SaveChanges() (That means a transaction is committed. Right ?).

您可以看到.在测试中,我尝试使用TransactionScope将多种服务方法包含在一个事务中.我的意思是在方法utilService.update()中.但是看来TransactionScopeSaveChanges() is called之后不起作用.所以我的问题是:

And you can see . In my test , I tried to use the TransactionScope to include multiple service method into one transaction. I mean it in the method utilService.update(). But It seems the TransactionScope not work after the SaveChanges() is called. So My question is :

是否有可能将其实现为我的想法?如果有 .我应该采用哪种模式? (我听说过UOW和存储库模式.它们是解决方案吗?谢谢.)

Is there any possibility to implement it as my idea ? If there is . What kind of pattern should I apply ? (I heard of UOW and Repository pattern . Are they the solution? Thanks.)

推荐答案

您需要实现工作单元模式以避免交易范围.Unit of WorkRepository Pattern是当今使用相当广泛的东西.

You need to implement Unit of work pattern to avoid transaction scope.Unit of Work and Repository Pattern is something used fairly widely nowadays.

UoW公开公共方法Commit来存储更改.

UoW exposes public method Commit to store the changes.

通用存储库

public class GenericRepository<TEntity> where TEntity : class
{
    internal SchoolContext context;
    internal DbSet<TEntity> dbSet;

    public GenericRepository(SchoolContext context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }

    public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")
    {
        IQueryable<TEntity> query = dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }

    public virtual TEntity GetByID(object id)
    {
        return dbSet.Find(id);
    }

    public virtual void Insert(TEntity entity)
    {
        dbSet.Add(entity);
    }

    public virtual void Delete(object id)
    {
        TEntity entityToDelete = dbSet.Find(id);
        Delete(entityToDelete);
    }

    public virtual void Delete(TEntity entityToDelete)
    {
        if (context.Entry(entityToDelete).State == EntityState.Detached)
        {
            dbSet.Attach(entityToDelete);
        }
        dbSet.Remove(entityToDelete);
    }

    public virtual void Update(TEntity entityToUpdate)
    {
        dbSet.Attach(entityToUpdate);
        context.Entry(entityToUpdate).State = EntityState.Modified;
    }
}

UnitOFWork

public class UnitOfWork : IDisposable
{
    //Context Creation in the UnitOfWork
    //This context is supplied to all Repository 
    //Hence One Commit save All Changes
    private SchoolContext context = new SchoolContext();
    private GenericRepository<Department> departmentRepository;
    private GenericRepository<Course> courseRepository;

    public GenericRepository<Department> DepartmentRepository
    {
        get
        {

            if (this.departmentRepository == null)
            {
                this.departmentRepository = new GenericRepository<Department>(context);
            }
            return departmentRepository;
        }
    }

    public GenericRepository<Course> CourseRepository
    {
        get
        {

            if (this.courseRepository == null)
            {
                this.courseRepository = new GenericRepository<Course>(context);
            }
            return courseRepository;
        }
    }

    public void Save()
    {
        context.SaveChanges();
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

用法

  //Sample Controller
 public class CourseController : Controller
   {
      //Initialize the unit of work here
      private UnitOfWork unitOfWork = new UnitOfWork();

      Public Void MyBussinessTransaction()
      {
         unitOfWork.CourseRepository.Insert(course);
         unitOfWork.DepartmentRepository.Insert(department)
         unitOfWork.Save();
      }
   }

UOW的马丁·弗劳德解释

这篇关于一次交易中调用多种服务方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆