Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

只依赖freesql基础包的情况下如何使用事务? #463

Closed
ignite-404 opened this issue Sep 16, 2020 · 7 comments
Closed

只依赖freesql基础包的情况下如何使用事务? #463

ignite-404 opened this issue Sep 16, 2020 · 7 comments

Comments

@ignite-404
Copy link

fsql.transaction(()=>{});用起来不友好,并且不支持异步。
但似乎可以通过masterpool.get()拿到ado connection 从而开启事务,
但是既然是一个pool每次get可能不是同一个链接,这样即便可以开启事务,用起来也很别扭。

最后我看了ado provider源码,提供了开启事务的方法,但是接口没有暴露出来。

public void BeginTransaction(IsolationLevel? isolationLevel)
        {
            if (TransactionCurrentThread != null) return;

            int tid = Thread.CurrentThread.ManagedThreadId;
            Transaction2 tran = null;
            Object<DbConnection> conn = null;
            var before = new Aop.TraceBeforeEventArgs("ThreadTransaction", isolationLevel);
            _util?._orm?.Aop.TraceBeforeHandler?.Invoke(this, before);

            try
            {
                conn = MasterPool.Get();
                tran = new Transaction2(conn, isolationLevel == null ? conn.Value.BeginTransaction() : conn.Value.BeginTransaction(isolationLevel.Value), TimeSpan.FromSeconds(60));
                tran.AopBefore = before;
            }
            catch (Exception ex)
            {
                Trace.WriteLine($"数据库出错(开启事务){ex.Message} \r\n{ex.StackTrace}");
                MasterPool.Return(conn);
                var after = new Aop.TraceAfterEventArgs(before, "", ex);
                _util?._orm?.Aop.TraceAfterHandler?.Invoke(this, after);
                throw ex;
            }
            if (_trans.ContainsKey(tid)) CommitTransaction();
            _trans.TryAdd(tid, tran);
        }
@2881099
Copy link
Collaborator

2881099 commented Sep 16, 2020

扩展阅读:IFreeSql 事务另类玩法,理解上面各种事务场景之后再看会更佳
#322

@2881099
Copy link
Collaborator

2881099 commented Sep 16, 2020

按照 2楼给的链接,重新封装一个 IFreeSql 出来使用

@ignite-404
Copy link
Author

我只想依赖基础包,并且为了使用事物要重新实现一个ifreesql难以接受。
事物作为一个非常基础的API不应该设计这么麻烦。

@2881099
Copy link
Collaborator

2881099 commented Sep 16, 2020

没有别的好办法,要么就只能每步Crud都用 WithTransaction 传递事务

@2881099
Copy link
Collaborator

2881099 commented Sep 16, 2020

AsyncLocal 倒是可以解决每步 Crud 都传递 WithTransaction 问题,不过之前测试 AsyncLocal 在一些平台报错,所以默认没有使用它

@2881099
Copy link
Collaborator

2881099 commented Sep 16, 2020

ado provider源码是基于线程事务的,即使暴露出来也不支持异步,还是要每步都要使用 WithTransaction 传递事务。

AsyncLocal 可以完美解决异步事务

另一种简单办法就是用 Aop 工作单元 + 仓储

@ignite-404
Copy link
Author

我看了源码,原来withtransaction会把开启事务的dbconnection赋值给当前的执行单元。所以我的问题解决了。

            using var trans = fsql.Ado.MasterPool.Get().Value.BeginTransaction();
            fsql.Select<test>().WithTransaction(trans);

谢谢

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

No branches or pull requests

2 participants