AsyncLocalCurrentUnitOfWorkProvider.cs 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using System.Threading;
  2. using Abp.Dependency;
  3. using Castle.Core;
  4. using Castle.Core.Logging;
  5. namespace Abp.Domain.Uow
  6. {
  7. /// <summary>
  8. /// CallContext implementation of <see cref="ICurrentUnitOfWorkProvider"/>.
  9. /// This is the default implementation.
  10. /// </summary>
  11. public class AsyncLocalCurrentUnitOfWorkProvider : ICurrentUnitOfWorkProvider, ITransientDependency
  12. {
  13. /// <inheritdoc />
  14. [DoNotWire]
  15. public IUnitOfWork Current
  16. {
  17. get { return GetCurrentUow(); }
  18. set { SetCurrentUow(value); }
  19. }
  20. public ILogger Logger { get; set; }
  21. private static readonly AsyncLocal<LocalUowWrapper> AsyncLocalUow = new AsyncLocal<LocalUowWrapper>();
  22. public AsyncLocalCurrentUnitOfWorkProvider()
  23. {
  24. Logger = NullLogger.Instance;
  25. }
  26. private static IUnitOfWork GetCurrentUow()
  27. {
  28. var uow = AsyncLocalUow.Value?.UnitOfWork;
  29. if (uow == null)
  30. {
  31. return null;
  32. }
  33. if (uow.IsDisposed)
  34. {
  35. AsyncLocalUow.Value = null;
  36. return null;
  37. }
  38. return uow;
  39. }
  40. private static void SetCurrentUow(IUnitOfWork value)
  41. {
  42. lock (AsyncLocalUow)
  43. {
  44. if (value == null)
  45. {
  46. if (AsyncLocalUow.Value == null)
  47. {
  48. return;
  49. }
  50. if (AsyncLocalUow.Value.UnitOfWork?.Outer == null)
  51. {
  52. AsyncLocalUow.Value.UnitOfWork = null;
  53. AsyncLocalUow.Value = null;
  54. return;
  55. }
  56. AsyncLocalUow.Value.UnitOfWork = AsyncLocalUow.Value.UnitOfWork.Outer;
  57. }
  58. else
  59. {
  60. if (AsyncLocalUow.Value?.UnitOfWork == null)
  61. {
  62. if (AsyncLocalUow.Value != null)
  63. {
  64. AsyncLocalUow.Value.UnitOfWork = value;
  65. }
  66. AsyncLocalUow.Value = new LocalUowWrapper(value);
  67. return;
  68. }
  69. value.Outer = AsyncLocalUow.Value.UnitOfWork;
  70. AsyncLocalUow.Value.UnitOfWork = value;
  71. }
  72. }
  73. }
  74. private class LocalUowWrapper
  75. {
  76. public IUnitOfWork UnitOfWork { get; set; }
  77. public LocalUowWrapper(IUnitOfWork unitOfWork)
  78. {
  79. UnitOfWork = unitOfWork;
  80. }
  81. }
  82. }
  83. }