From fc4e8344529fc9e3ddbe3f96f4525b37c20095cf Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Wed, 22 Apr 2020 03:54:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20UnitOfWorkManager=20?= =?UTF-8?q?=E7=B1=BB=E7=AE=A1=E7=90=86=E5=B7=A5=E4=BD=9C=E5=8D=95=E5=85=83?= =?UTF-8?q?=EF=BC=8C=E7=A7=BB=E9=99=A4=20FreeSql.UnitOfWork.Current=20?= =?UTF-8?q?=E9=9D=99=E6=80=81=E5=B1=9E=E6=80=A7=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BaseEntity 纯净版源码(.Net 4.0).zip | Bin 2698 -> 0 bytes .../BaseEntity 纯净版源码.zip | Bin 4439 -> 0 bytes .../BaseEntity.cs | 16 +- .../BaseEntityAsync.cs | 16 +- .../BaseEntityReadOnly.cs | 12 +- .../BaseEntityTree.cs | 4 +- FreeSql.DbContext/FreeSql.DbContext.xml | 42 +++- .../ContextSet/RepositoryUnitOfWorkManager.cs | 201 ++++++++++++++++++ FreeSql.DbContext/UnitOfWork/IUnitOfWork.cs | 5 +- FreeSql.DbContext/UnitOfWork/UnitOfWork.cs | 14 +- 10 files changed, 276 insertions(+), 34 deletions(-) delete mode 100644 Extensions/FreeSql.Extensions.BaseEntity/BaseEntity 纯净版源码(.Net 4.0).zip delete mode 100644 Extensions/FreeSql.Extensions.BaseEntity/BaseEntity 纯净版源码.zip create mode 100644 FreeSql.DbContext/Repository/ContextSet/RepositoryUnitOfWorkManager.cs diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity 纯净版源码(.Net 4.0).zip b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity 纯净版源码(.Net 4.0).zip deleted file mode 100644 index 6a90cb183bbb7a74c0e98cbb524ad08de5b0618b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2698 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 diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity 纯净版源码.zip b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity 纯净版源码.zip deleted file mode 100644 index 47a9b4d13018fbf8f0544cd4d91eb495eb312a33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4439 zcmZ{ocTf||*2WVlf`Eh~y+{BdkzPXYAU)I|MS8~oLXai~1OX``gbqqm>79Vmt007q z^rA$HAQ6I~Nd0{8-1mOo@11XVX3xy|W1rcbo!>s^80(XeG6Dbq3V>jvzft-^O$UM$ z0C+wrw=8)*T#5$WA-o2ft>xR*tsdUjgN#4@Fe|Q^V zk67RAxou=@p|L2-v)(%zvsKp7Xw^kOCbpp`REE>sZChf(NRek)%QtHKJ#AJu)u-kn zyxOU4KJ-Xs;EC~&xp^O6OT*4fJA8#H_Cxy?B!*p6s!pqAuB0T%(1?d+9?9g*X!r6_ zhyt_kFO++f{+J1uxvps;4Q6=}+d5Sw2#VEl3Reh$cDnll$-Z+(&c1PIe7o1z8A^AJ z%7b{;^DLLM6BR`4B|A9##@dMrCw`~7=pNXuVWJn65g%xNYIUgFasG?EeCN9N_&%M< zjfNzuA7pPno}WtH#_}%fKg$!o-x1L_*<5n|^5lHbXcevg0Omb+Yu<dQmWB*%xY`KHyM}Sr z2jjZc3xq9`K|}o%lh%YN4(oj7sAb;!mvUb6zxNPcC4pimK=HX2>W@+=X&?9#JsgwP zcqXf{xoi?)OXY=PF0kBI#Q~F;vR?X{4`pH!?8m!PPzn5r5*etIS{}_oBWLP3asYVu zvX9+urEw586#baBV$zzlGXZ+XZKfQz#WPXNf!Xl+2BVC%xf}l@C((*gEBCQifFg$c zc~;)G@T4xCuYepZ-aY4P$Sjd;=0%4NCfn_V92r@C{`f{8+ zBHXFR=jCvoiD?WhV*w|bqApBQvdWvKXC4#ktc&WzhZWMOmbpe;GGoxZX;?R5d<8I5 zy9QJq(}}AJ-L~+^LZ8yUCmLxMsgS1(E}Y!-Kdl$B_x9D!AHUce8@W_1W$h&mwlzePIixt8Z7^COLY`@cV`1jCL(!YN2S2E_4!syo5r%t&*WmL zmxynL>1cttX69t!bh=_##bvXbCgyRlgY^TkpJrAy_l8NE%z@HBB%u1!XCf*t8%m>v z$+;(t_>ql3uzna-nMp?4SfXj$pf8dCcaXAU5$9Q=$%zMM)5o>mu+2|r(brts{xd33*^sL5x&dfgBS<^>5=(UAih z=Rz8|(muESRdEfwYUqxVW<+adx9z(mz^Bg^7Y}?Re`Qw0%U0g&hw^!r%E2c)^U{;O zTxUO9w)eX3OPnq%$_wE^{<<#7=})Fz9&8X{({BK6caB6?IYSnDqNT&)s3k8 zH;m3tv?AmA z4gvt^|BF9rs1P6Le?iD5VM>(|Eqb6rt=xDW(y?tlQKd&$iF~R2gtlQYKp_jhJ?tX= z8$!Xi_v(ux$RzxSq!wjX@sI1W8AA8&0vAX?wsJ)31tU_G%N z_PbwRR9s2RUBiRAOjN@?(9Eus713l}2|GLMeb>VI)egPq()^Q>FJnycD%TQCQuz1@ zDbl5TQeerbifreFKJAUE$HJxs|l%Ca}{R4xNUH5OD-wij1%^DzPQMIMJzbK z$r#d}FBsvUF){JdBbpbn?vFQ?XKQmdXobz+YEIsJXB_|^Fy4OfI&-~o+aIlit&4wE zm(Xh4vpSR0(q4@GptXF%+R!`?2^ffvc1hVy3s9hHHmSvZ2+Q-|a@3AuPYxp;p=$x3a5vn8@@A(J@Z70e~PQg;k7@ zu6bp>FkqWc2E7eoNtn~pC9L*{D8*WwXeF+lrGb@|!yjwhk$SH#xi=$~_4xuy2l>+H zkbU2_Bp$Cxzz1;Em*6Vk0OllZa)(p_76&fpm;hU~*SLpTH>gV?9ciMC8~eI?K%@ra)3s ziErQiHW6?4!kp+dm)rC>RO8}ahF7LHreM=ALU&H}jFh zRPM|H@6dJ?`KG<)?~wRklnp)M_Cw^e1R1#Q=dC%~|HaBd8O8_|qz$9F3;@`$0szXzd<9xx^$u3}f1n5G_{?r1g}w{0pS@fyiPUMD53i67c#nc4&P zzA`XVkoB2P94r-gUDKHdr`_^Q$*rXj=>ixW2ua?H8<()qom$Fs9SF_f2|hkPHdblW z=SL#y&y!JG1_Zpm6tw}%peO(2n}$0c=%h(QO@Ty4J3k z#h+{U>;xunJl+2p{LXkF+qGi2iDKyb5#PSDnpM;HmSXVplHnexMtKrMOCt+I7v)(A zE`9rBMWfrf*5N|~H9@9oGEhHPj|#)WYZH@~jauRQdArwXZ8+Sk?IHLJo_ZfaFm|A} zbg36s8t(!)F=T|Wu&#-*$rWKFXs>!Ym$&S-qaTjSg*S^|bZ3WrQtbS4r-fAv!743P z>}abHzkDsMUBKo2%)zBPzGnCA`c#ZsZnk%U9>?#8KPN>^mn=p@$3xu1A%--8x7c{w z1=FEjprT^$GQM64S3RD5kyYMOWR85%f(gbdSI-Y!?Vy`61z`oi$^E9JKGwq``E8bN zG$aZ?C+wo^31-ADp{LrHPBC3?NDGCNTL&Bx5R^o|u~+c{rbe#3c&jJScm2C*W!H=; zE|}OyrzH!r(dVCIL;Lv+w8x-PZdR;KRXrd`PVk~&50Pu?rq_$TjZ&U*v%j2E7) zMJ8AjeXzS*lX3+t{z7V}gDa?dRDnAW!Te1j(^u9Vj!>}=5aD}&H)shA5+Ns}4Y4Q2 zbuy^3-~0xv((rh~F-{$4v-Xg!sTxPAKamgNpuY6NfbPkqx{mYhu(R)|v9s{0VH2-y zpXbPRJUJ+{MJLU`k!s$UT(V6aTGV)?$lt7llr5VS0a~9nIeBMZYL{a<|#qi08Zqy@hp zZa(vpO zYs0lY?&`PeWy4TYLFU3w z?#Z|t3r@8Bt}?VKjs}Q3*XcK!FL!3a%v3E-FQrj#K1f6NY;pY@KMg>NA1po`r*%8O z9`x$!M}o8>HATs%K(D_zr#D(FC|Z zPPL=7U)jFJsv)96Hcb;mtfG1h#@z9e^-|*}@eZp}klrhrDso9^T%*enmR-TZSkzjyot>iyxy*(W=`~*^rAO?uytP1E>uh} z>9pr1S2&?6kO1j@9@uQZp};*l;v31SB<7g#wPPT3@73}8*;q|xu*MI0aSK%^rYbxB z-eAIU7-5pq{rs-;MzpMQLi8&Cy-qPl>meP=yYd6Vjc&^=(-ku{A7$mrO5Gs*K|yW< zt4}!~CH3+m>r`)vF4aUr?)UpY#*BPd3Hf5ZooYKDk?dZm7UuQU4REejLBfNqYZce( zD99POqQDaykog3#_%5j;cALAWI_H+!=aX*p44itS&FC%x*2JLA0+x@&UUDcy-};piItv19|BzT3^w%9i@{A#oaBW zuZ1$$5Y^N0jPKZON#Ukb8ZUC2RL>4eA7M4%Hn~s0d(ki(Hg^$i`!{=K?{SZ|?2Yw- zms9}%Ut@sp_aFM#xc;y8|Fj9N{5uT__Zn+E%WgeM*i0|ko=xdAOOJpyL15n{s)%u8c+ZL diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs index 829e33c5..a3064ad9 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs @@ -70,12 +70,12 @@ namespace FreeSql { if (this.Repository == null) return Orm.Update(this as TEntity) - .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) + .WithTransaction(CurrentUnitOfWork?.GetOrBeginTransaction()) .Set(a => (a as BaseEntity).IsDeleted, this.IsDeleted = value).ExecuteAffrows() == 1; this.SetTenantId(); this.IsDeleted = value; - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return this.Repository.Update(this as TEntity) == 1; } /// @@ -89,7 +89,7 @@ namespace FreeSql if (this.Repository == null) return Orm.Delete(this as TEntity).ExecuteAffrows() == 1; //this.SetTenantId(); - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return this.Repository.Delete(this as TEntity) == 1; } /// @@ -107,11 +107,11 @@ namespace FreeSql this.UpdateTime = DateTime.Now; if (this.Repository == null) return Orm.Update() - .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) + .WithTransaction(CurrentUnitOfWork?.GetOrBeginTransaction()) .SetSource(this as TEntity).ExecuteAffrows() == 1; this.SetTenantId(); - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return this.Repository.Update(this as TEntity) == 1; } /// @@ -124,7 +124,7 @@ namespace FreeSql this.Repository = Orm.GetRepository(); this.SetTenantId(); - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return this.Repository.Insert(this as TEntity); } @@ -139,7 +139,7 @@ namespace FreeSql this.Repository = Orm.GetRepository(); this.SetTenantId(); - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return this.Repository.InsertOrUpdate(this as TEntity); } @@ -152,7 +152,7 @@ namespace FreeSql if (this.Repository == null) this.Repository = Orm.GetRepository(); - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; this.Repository.SaveMany(this as TEntity, navigatePropertyName); } } diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs index fb43fcb9..8b0e5ed2 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs @@ -53,11 +53,11 @@ namespace FreeSql { if (this.Repository == null) return await Orm.Update(this as TEntity) - .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) + .WithTransaction(CurrentUnitOfWork?.GetOrBeginTransaction()) .Set(a => (a as BaseEntity).IsDeleted, this.IsDeleted = value).ExecuteAffrowsAsync() == 1; this.IsDeleted = value; - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return await this.Repository.UpdateAsync(this as TEntity) == 1; } /// @@ -71,7 +71,7 @@ namespace FreeSql if (this.Repository == null) return await Orm.Delete(this as TEntity).ExecuteAffrowsAsync() == 1; //this.SetTenantId(); - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return await this.Repository.DeleteAsync(this as TEntity) == 1; } /// @@ -89,11 +89,11 @@ namespace FreeSql this.UpdateTime = DateTime.Now; if (this.Repository == null) return await Orm.Update() - .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) + .WithTransaction(CurrentUnitOfWork?.GetOrBeginTransaction()) .SetSource(this as TEntity).ExecuteAffrowsAsync() == 1; this.SetTenantId(); - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return await this.Repository.UpdateAsync(this as TEntity) == 1; } /// @@ -106,7 +106,7 @@ namespace FreeSql this.Repository = Orm.GetRepository(); this.SetTenantId(); - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return this.Repository.InsertAsync(this as TEntity); } @@ -121,7 +121,7 @@ namespace FreeSql this.Repository = Orm.GetRepository(); this.SetTenantId(); - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return this.Repository.InsertOrUpdateAsync(this as TEntity); } @@ -134,7 +134,7 @@ namespace FreeSql if (this.Repository == null) this.Repository = Orm.GetRepository(); - this.Repository.UnitOfWork = UnitOfWork.Current.Value; + this.Repository.UnitOfWork = CurrentUnitOfWork; return this.Repository.SaveManyAsync(this as TEntity, navigatePropertyName); } } diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs index 68174990..d4efcbff 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs @@ -106,9 +106,11 @@ namespace FreeSql { var uow = Orm.CreateUnitOfWork(); uow.IsolationLevel = level; + CurrentUnitOfWork = uow; return uow; } + static readonly AsyncLocal _AsyncUnitOfWork = new AsyncLocal(); static readonly AsyncLocal _AsyncTenantId = new AsyncLocal(); /// /// 获取或设置当前租户id @@ -118,6 +120,14 @@ namespace FreeSql get => _AsyncTenantId.Value; set => _AsyncTenantId.Value = value; } + /// + /// 获取或设置当前租户id + /// + public static IUnitOfWork CurrentUnitOfWork + { + get => _AsyncUnitOfWork.Value; + set => _AsyncUnitOfWork.Value = value; + } } /// @@ -143,7 +153,7 @@ namespace FreeSql { var select = Orm.Select() .TrackToList(TrackToList) //自动为每个元素 Attach - .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction(false)); + .WithTransaction(CurrentUnitOfWork?.GetOrBeginTransaction(false)); if (string.IsNullOrEmpty(CurrentTenantId) == false) select.WhereCascade(a => (a as ITenant).TenantId == CurrentTenantId); return select.WhereCascade(a => (a as BaseEntity).IsDeleted == false); diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityTree.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityTree.cs index 28be88c8..a2b5231c 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityTree.cs +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityTree.cs @@ -79,7 +79,7 @@ namespace FreeSql buf.Add(this as TEntity); buf.AddRange(this.GetAllChilds()); var repo = Orm.GetRepository(); - repo.UnitOfWork = UnitOfWork.Current.Value; + repo.UnitOfWork = CurrentUnitOfWork; buf = repo.Select.WhereDynamic(buf) .Include(a => ((((((((((a as BaseEntityTree).Parent as BaseEntityTree).Parent @@ -110,7 +110,7 @@ namespace FreeSql var childs = GetAllChilds(); childs.Add(this as TEntity); var repo = Orm.GetRepository(); - repo.UnitOfWork = UnitOfWork.Current.Value; + repo.UnitOfWork = CurrentUnitOfWork; repo.Attach(childs); foreach (var item in childs) (item as BaseEntity).IsDeleted = false; diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index f619f03f..9f17feac 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -227,6 +227,41 @@ 分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository + + + 仓储的工作单元管理器 + + + + + 如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,默认的选择。 + + + + + 支持当前事务,如果没有当前事务,就以非事务方法执行。 + + + + + 使用当前事务,如果没有当前事务,就抛出异常。 + + + + + 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 + + + + + 以非事务方式执行操作,如果当前事务存在则抛出异常。 + + + + + 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就新建一个事务。 + + 开启过滤器,若使用 using 则使用完后,恢复为原有状态 @@ -299,6 +334,11 @@ 实体对象 属性名 + + + 工作单元 + + 开启事务,或者返回已开启的事务 @@ -326,7 +366,7 @@ - 此工作单元内的实体变化跟踪 + 工作单元内的实体变化跟踪 diff --git a/FreeSql.DbContext/Repository/ContextSet/RepositoryUnitOfWorkManager.cs b/FreeSql.DbContext/Repository/ContextSet/RepositoryUnitOfWorkManager.cs new file mode 100644 index 00000000..a3524b59 --- /dev/null +++ b/FreeSql.DbContext/Repository/ContextSet/RepositoryUnitOfWorkManager.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; + +namespace FreeSql +{ + /// + /// 仓储的工作单元管理器 + /// + public class RepositoryUnitOfWorkManager : IDisposable + { + IFreeSql _fsql; + List _uows = new List(); + bool _isNotSupported = false; + + public RepositoryUnitOfWorkManager(IFreeSql fsql) + { + _fsql = fsql ?? throw new ArgumentNullException($"{nameof(RepositoryUnitOfWorkManager)} 构造参数 {nameof(fsql)} 不能为 null"); + } + + ~RepositoryUnitOfWorkManager() => this.Dispose(); + int _disposeCounter; + public void Dispose() + { + if (Interlocked.Increment(ref _disposeCounter) != 1) return; + try + { + Exception exception = null; + for (var a = _uows.Count - 1; a >= 0; a--) + { + try + { + if (exception == null) _uows[a].Commit(); + else _uows[a].Rollback(); + } + catch (Exception ex) + { + if (exception == null) exception = ex; + } + } + if (exception != null) throw exception; + } + finally + { + _uows.Clear(); + GC.SuppressFinalize(this); + } + } + + public enum Propagation + { + /// + /// 如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,默认的选择。 + /// + Requierd, + /// + /// 支持当前事务,如果没有当前事务,就以非事务方法执行。 + /// + Supports, + /// + /// 使用当前事务,如果没有当前事务,就抛出异常。 + /// + Mandatory, + /// + /// 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 + /// + NotSupported, + /// + /// 以非事务方式执行操作,如果当前事务存在则抛出异常。 + /// + Never, + /// + /// 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就新建一个事务。 + /// + Nested + } + + public IRepositoryUnitOfWork Begin(Propagation propagation, IsolationLevel? isolationLevel = null) + { + if (propagation == Propagation.Requierd) + { + if (_isNotSupported == false) + { + for (var a = _uows.Count - 1; a >= 0; a--) + if (_uows[a].GetOrBeginTransaction(false) != null) + return new UnitOfWorkProxy(_uows[a]); + } + var uow = new RepositoryUnitOfWork(_fsql); + if (isolationLevel != null) uow.IsolationLevel = isolationLevel.Value; + try { uow.GetOrBeginTransaction(); } + catch { uow.Dispose(); throw; } + _uows.Add(uow); + return uow; + } + if (propagation == Propagation.Supports) + { + if (_isNotSupported == false) + { + for (var a = _uows.Count - 1; a >= 0; a--) + if (_uows[a].GetOrBeginTransaction(false) != null) + return new UnitOfWorkProxy(_uows[a]); + } + return new UnitOfWorkNothing(_fsql); + } + if (propagation == Propagation.Mandatory) + { + if (_isNotSupported == false) + { + for (var a = _uows.Count - 1; a >= 0; a--) + if (_uows[a].GetOrBeginTransaction(false) != null) + return new UnitOfWorkProxy(_uows[a]); + throw new Exception("Propagation_Mandatory: 使用当前事务,如果没有当前事务,就抛出异常"); + } + throw new Exception("Propagation_Mandatory: 使用当前事务,如果没有当前事务,就抛出异常(NotSupported 事务挂起中)"); + } + if (propagation == Propagation.NotSupported) + { + if (_isNotSupported == false) + { + _isNotSupported = true; + return new UnitOfWorkNothing(_fsql) { OnDispose = () => _isNotSupported = false }; + } + return new UnitOfWorkNothing(_fsql); + } + if (propagation == Propagation.Never) + { + if (_isNotSupported == false) + { + for (var a = _uows.Count - 1; a >= 0; a--) + if (_uows[a].GetOrBeginTransaction(false) != null) + throw new Exception("Propagation_Never: 以非事务方式执行操作,如果当前事务存在则抛出异常"); + } + return new UnitOfWorkNothing(_fsql); + } + if (propagation == Propagation.Nested) + { + var uow = new RepositoryUnitOfWork(_fsql); + if (isolationLevel != null) uow.IsolationLevel = isolationLevel.Value; + try { uow.GetOrBeginTransaction(); } + catch { uow.Dispose(); throw; } + _uows.Add(uow); + return uow; + } + throw new NotImplementedException(); + } + + class UnitOfWorkProxy : IRepositoryUnitOfWork + { + IRepositoryUnitOfWork _baseUow; + public UnitOfWorkProxy(IRepositoryUnitOfWork baseUow) => _baseUow = baseUow; + public IsolationLevel? IsolationLevel { get => _baseUow.IsolationLevel; set { } } + public DbContext.EntityChangeReport EntityChangeReport => _baseUow.EntityChangeReport; + + public bool Enable => _baseUow.Enable; + public void Close() => _baseUow.Close(); + public void Open() => _baseUow.Open(); + + public DbTransaction GetOrBeginTransaction(bool isCreate = true) => _baseUow.GetOrBeginTransaction(isCreate); + public void Commit() => this.Dispose(); + public void Rollback() => _baseUow.Rollback(); + public void Dispose() { } + + public IBaseRepository GetRepository(Expression> filter = null) where TEntity : class => _baseUow.GetRepository(filter); + public IBaseRepository GetRepository(Expression> filter = null) where TEntity : class => _baseUow.GetRepository(filter); + public IBaseRepository GetGuidRepository(Expression> filter = null, Func asTable = null) where TEntity : class => _baseUow.GetGuidRepository(filter); + } + class UnitOfWorkNothing : IRepositoryUnitOfWork + { + internal IFreeSql _fsql; + internal Action OnDispose; + public UnitOfWorkNothing(IFreeSql fsql) => _fsql = fsql; + public IsolationLevel? IsolationLevel { get; set; } + public DbContext.EntityChangeReport EntityChangeReport { get; } = new DbContext.EntityChangeReport(); + + public bool Enable { get; } + public void Close() { } + public void Open() { } + + public DbTransaction GetOrBeginTransaction(bool isCreate = true) => null; + public void Commit() + { + if (EntityChangeReport != null && EntityChangeReport.OnChange != null && EntityChangeReport.Report.Any() == true) + EntityChangeReport.OnChange.Invoke(EntityChangeReport.Report); + this.Dispose(); + } + public void Rollback() => this.Dispose(); + public void Dispose() { + EntityChangeReport?.Report.Clear(); + OnDispose?.Invoke(); + } + + public IBaseRepository GetRepository(Expression> filter = null) where TEntity : class => new DefaultRepository(_fsql, filter); + public IBaseRepository GetRepository(Expression> filter = null) where TEntity : class => new DefaultRepository(_fsql, filter); + public IBaseRepository GetGuidRepository(Expression> filter = null, Func asTable = null) where TEntity : class => new GuidRepository(_fsql, filter, asTable); + } + } +} diff --git a/FreeSql.DbContext/UnitOfWork/IUnitOfWork.cs b/FreeSql.DbContext/UnitOfWork/IUnitOfWork.cs index e6ffb167..dfc5e034 100644 --- a/FreeSql.DbContext/UnitOfWork/IUnitOfWork.cs +++ b/FreeSql.DbContext/UnitOfWork/IUnitOfWork.cs @@ -5,6 +5,9 @@ using System.Data.Common; namespace FreeSql { + /// + /// 工作单元 + /// public interface IUnitOfWork : IDisposable { @@ -40,7 +43,7 @@ namespace FreeSql void Open(); /// - /// 此工作单元内的实体变化跟踪 + /// 工作单元内的实体变化跟踪 /// DbContext.EntityChangeReport EntityChangeReport { get; } } diff --git a/FreeSql.DbContext/UnitOfWork/UnitOfWork.cs b/FreeSql.DbContext/UnitOfWork/UnitOfWork.cs index 4e0aa3de..941cdac8 100644 --- a/FreeSql.DbContext/UnitOfWork/UnitOfWork.cs +++ b/FreeSql.DbContext/UnitOfWork/UnitOfWork.cs @@ -11,10 +11,6 @@ namespace FreeSql { public class UnitOfWork : IUnitOfWork { -#if netcoreapp - public static readonly AsyncLocal Current = new AsyncLocal(); -#endif - static int _seed; /// /// 正在使用中的工作单元(调试) @@ -40,11 +36,7 @@ namespace FreeSql if (_fsql == null) throw new ArgumentNullException(nameof(fsql)); _uowBefore = new Aop.TraceBeforeEventArgs("UnitOfWork", null); - _fsql?.Aop.TraceBeforeHandler?.Invoke(this, _uowBefore); - -#if netcoreapp - Current.Value = this; -#endif + _fsql.Aop.TraceBeforeHandler?.Invoke(this, _uowBefore); } void ReturnObject() @@ -55,9 +47,6 @@ namespace FreeSql _fsql.Ado.MasterPool.Return(_conn); _tran = null; _conn = null; -#if netcoreapp - Current.Value = null; -#endif EntityChangeReport?.Report.Clear(); } @@ -174,7 +163,6 @@ namespace FreeSql try { this.Rollback(); - this.Close(); } finally {