关于异步、DDD、事务的几个问题。

来源:1-1 课前须知,这里有你需要了解的一切

黑白二进制

2021-07-25

有几个问题想请教老师,以下问题均在 .net5, ef core环境下

  1. 事务应该怎么开启与使用。
    我已经浏览过微软相关文档,搞不清楚怎么使用课程中的 AppDbContext 替换?
using var context = new BloggingContext();

我尝试直接使用 _context 开启事务上下文,从自己的测试来看是成功进行事务的回退,但不清楚这是否正确的开启方式。

 public void 新增大纲节点(大纲节点Model 大纲节点Model)
 {
     using var transaction = _context.Database.BeginTransaction();
     try
     {
         _context.大纲节点关系表.Add(new 大纲节点关系Model {
             节点Id = 3,
             祖先Id = 3,
             距离 = 0
         });
         _context.SaveChanges();

         _context.大纲节点表.Add(大纲节点Model);
         _context.SaveChanges();

         transaction.Commit();
     }
     catch (Exception ex)
     {
         // TODO: Handle failure
         Console.WriteLine(ex);
     }
 }

而上述存在一个问题是,事务的开启与函数耦合了,只能实现单次的事务,如果希望控制一批数据的提交就不合适。这就引申出第二个问题。
2. 我希望实现类似课程中的 save() 方法,将 startTransactiontransaction.Commit()剥离出来,达到可以在 controller 中,开启事务,执行多个 ef core command 后,再统一 commit。
那是否需要像下图一样,重新生成一个链接,与一个数据库上下文呢?
微软文档
3. 关于课程中讲解异步部分,我尝试不加 async,使用常规同步的方式,在 repo 文件中新增 sleep(5000) 函数后,同时发起两个请求,没有预想中的被阻塞现象出现,这是为什么呢?
4. 我觉得老师讲解得非常好,希望能继续学习更深的知识,例如现在非常流行微服务、DDD,请问有计划在近段时间开展相关课程吗?

写回答

1回答

阿莱克斯刘

2021-08-05

同学你好,打疫苗烧了几天耽搁了回复,不好意思。


1. 你的第一个问题,没毛病,transaction基本的使用方式就是如你代码所述。


2. 第二个问题,不知道你有没有java springboot的使用经验,java对事务管理做的就非常好。它采用一个叫做@transactional的annotation来管理事务,@transactional可以放在controller级别,也可以放在service级别,甚至是service某一个函数级别。所以,我们可以借用java的思想,使用action filter来进行处理

public class TransactionalAttribute : Attribute, IAsyncActionFilter{    
    public async Task OnActionExecutionAsync(
        ActionExecutingContext context, 
        ActionExecutionDelegate next)
    {        
        using (var transactionScope = new TransactionScope())
        {
            ActionExecutedContext actionExecutedContext = await next();           
            //if no exception were thrown
            if (actionExecutedContext.Exception == null)
                transactionScope.Complete();
        }
    }
}
public class HomeController : Controller {    //...    

    [Transactional]    
    public IActionResult Test() { /*some code */ }    
    //...
}

stackoverflow 有相关的回答:https://stackoverflow.com/questions/57441301/transactional-annotation-attribute-in-net-core


3.  对于同步与异步的对比测试,只是简单跑两个请求是不足够的,一般情况下我们无法看出同步与异步的差别。原因是你电脑的thread pool还没耗尽,iis或者kestly服务器还有足够的空间运行新的线程。

所以测试的第一步就需要到你的代码中修改ThreadPool大小,截图如下:

//img.mukewang.com/szimg/610ae47b0991a12f14040218.jpg

接着使用load test工具来做测试,windows推荐使用websurge,https://websurge.west-wind.com/

然后你就会发现没带async的请求会越来越慢,甚至出现失败的情况。


4. 关于后续的课程,我正在规划DDD+微服务相关的内容,目前正在起草大纲阶段,具体内容还需要与慕课网商量。谢谢你的支持。

1
0

.Net 开发电商后端API 从0到精通RESTful

. Net 实战+RESTful思想纵深课程,开发优雅RESTful风格API。

978 学习 · 547 问题

查看课程