Skip to content
This repository has been archived by the owner on May 8, 2021. It is now read-only.

沙发,关于 Cap 接入问题建议 #1

Open
2881099 opened this issue Mar 13, 2020 · 4 comments
Open

沙发,关于 Cap 接入问题建议 #1

2881099 opened this issue Mar 13, 2020 · 4 comments

Comments

@2881099
Copy link

2881099 commented Mar 13, 2020

大哥好,你现在这样封装肯定可以。

问题初衷:

如何在外部控制事务提交?

因为提交事务的操作中可能还有其他操作,不是简单 tran.Commit() 就完事。

如果把事务提交权交给 Cap,整个事务就终断。

伪代码如下:

using (var uow = ....())
{
    _capPublisher.Transaction.Value.Begin(uow.Transaction);
    //...
    uow.Commit(); // 这样提交 _capPublisher.Flush 没有被执行
}
using (var uow = ....())
{
    _capPublisher.Transaction.Value.Begin(uow.Transaction);
    //...
    capPublisher.Commit(); // 这样提交 uow.Commit 内部其他逻辑没有被执行
}

建议:开放 Flush 方法给外部使用

Cap 作者否决了我的意图,不给支持,其实很简单的一个改动。如果每个数据库自己 copy 代码来改比较复杂,建议代码如下:

public static class CapUnitOfWorkExtenssions
{
    public static void SetCapPublisher(this IUnitOfWork fsql, ICapPublisher capPublisher)
    {
        capPublisher.Transaction.Value.Begin(uow.GetOrBeginTransaction());
    }
    public static void Flush(this ICapPublisher capPublisher)
    {
        capPublisher?.GetType().GetMethod("Flush", BindingFlags.Instance | BindingFlags.NonPublic)
            .Invoke(capPublisher, null);
    }
}

using (var uow = fsql.CreateUnitOfWork())
{
    uow.SetCapPublisher(_capPublisher);
    //...
    uow.Commit();
    capPublisher.Flush(); //执行 mq 推送
}

这样一来就不用为每个数据库去做这个了

@2881099
Copy link
Author

2881099 commented Mar 13, 2020

有空的时候,我们讨论一下

@luoyunchong
Copy link
Owner

有空的时候,我们讨论一下

嗯。你才是大佬,哈哈。。我也就按照你之前指导的,分析了内部dapper和ef core关于事务的提交,修改了内部代码,CAP事务不同数据库、ORM,都要适配,感觉设计不太好。不过我找不到啥办法。

@2881099
Copy link
Author

2881099 commented Mar 13, 2020

看看我后面贴的代码,用反射去执行 flush 方法,使用习惯基本就和平时使用 ORM 差不多了

@luoyunchong
Copy link
Owner

luoyunchong commented May 23, 2020

按照大佬的思路,可以不改变CAP的代码基础上,我们可以这样写一个扩展方法。仅安装官方提供的包。

Install-Package DotNetCore.CAP.Dashboard
Install-Package DotNetCore.CAP.MySql
Install-Package DotNetCore.CAP.RabbitMQ
Install-Package FreeSql
Install-Package FreeSql.DbContext
Install-Package FreeSql.Provider.MySqlConnector

  public static class CapUnitOfWorkExtensions
    {
        public static ICapTransaction  BeginTransaction(this IUnitOfWork unitOfWork, ICapPublisher publisher, bool autoCommit = false)
        {
            publisher.Transaction.Value = publisher.ServiceProvider.GetService<ICapTransaction>();
            return publisher.Transaction.Value.Begin(unitOfWork.GetOrBeginTransaction(), autoCommit);
        }
        
        public static void Flush(this ICapTransaction capTransaction)
        {
            capTransaction?.GetType().GetMethod("Flush", BindingFlags.Instance | BindingFlags.NonPublic)
                ?.Invoke(capTransaction, null);
        }
        
        public static void Commit(this IUnitOfWork unitOfWork,ICapTransaction capTransaction)
        {
            unitOfWork.Commit();
            capTransaction.Flush();
        }
    }

使用demo,完整项目可查看 https://github.com/luoyunchong/DotNetCore.CAP.Provider/tree/master/samples/Sample.RabbitMQ.MySql.FreeSql

[HttpGet("~/freesql/flush/{id}")]
public DateTime Flush(int id = 0)
{
    DateTime now = DateTime.Now;
    using (var uow = _freeSql.CreateUnitOfWork())
    {
        //这个不能使用using,因为这个using掉,uow.Dispose()时就会导致FreeSql,提示cannot access dispose transaction
        ICapTransaction trans = uow.BeginTransaction(_capBus, false);
        var repo = uow.GetRepository<WeatherForecast>();
        repo.Insert(new WeatherForecast()
        {
            Date = now,
            Summary = "summary" + (id == 1
                ? "summarysummarysummarysummarysummarysummarysummarysummarysummarysummarysummary"
                : ""),
            TemperatureC = 100
        });

        if (id == 0)
        {
            throw new Exception("异常,事务不正常!!");
        }

        repo.Insert(new WeatherForecast()
        {
            Date = now,
            Summary = "11222",
            TemperatureC = 200
        });

        _capBus.Publish("FreeSqlController.time", now);

        uow.Commit(trans);
    }

    return now;
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants