From 9824f0ff4788972c6a7faa51c3b09333b67210f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Mon, 15 Jun 2020 16:25:57 +0300 Subject: [PATCH] Add sections to the UOW document --- docs/en/Unit-Of-Work.md | 140 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 1 deletion(-) diff --git a/docs/en/Unit-Of-Work.md b/docs/en/Unit-Of-Work.md index a16184e0eb..56c3486ad6 100644 --- a/docs/en/Unit-Of-Work.md +++ b/docs/en/Unit-Of-Work.md @@ -25,5 +25,143 @@ A UOW automatically begins for these methods **except** if there is already a ** * If you call an [application service](Application-Services.md) method, the same UOW system works just as explained above. If the application service method uses some repositories, the repositories **don't begin a new UOW**, but **participates to the current unit of work** started by the ABP Framework for the application service method. * The same is true for an ASP.NET Core controller action. If the operation has started with a controller action, then the **UOW scope is the controller action's method body**. -All of these are automatically handled by the ABP Framework. The rest of this document explains the UOW system in details and options provided to fine control the UOW system. +All of these are automatically handled by the ABP Framework. +### Database Transaction Behavior + +While the section above explains the UOW as it is database transaction, actually a UOW doesn't have to be transactional. By default; + +* **HTTP GET** requests don't start a transactional UOW. They still starts a UOW, but **doesn't create a database transaction**. +* All other HTTP request types start a UOW with a database transaction, if database level transactions are supported by the underlying database provider. + +This is because an HTTP GET request doesn't (and shouldn't) make any change in the database. You can change this behavior using the options explained below. + +## Default Options + +... + +## Controlling the Unit Of Work + +In some cases, you may want to change the conventional transaction scope, create inner scopes or fine control the transaction behavior. The following sections cover these possibilities. + +### IUnitOfWorkEnabled Interface + +This is an easy way to enable UOW for a class (or a hierarchy of classes) that is not unit of work by the conventions explained above. + +**Example: Implement `IUnitOfWorkEnabled` for an arbitrary service** + +````csharp +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Uow; + +namespace AbpDemo +{ + public class MyService : ITransientDependency, IUnitOfWorkEnabled + { + public virtual async Task FooAsync() + { + //this is a method with a UOW scope + } + } +} +```` + +Then `MyService` (and any class derived from it) methods will be UOW. + +However, there are **some rules should be followed** in order to make it working; + +* If you are **not injecting** the service over an interface (like `IMyService`), then the methods of the service must be `virtual` (otherwise, [dynamic proxy / interception](Dynamic-Proxying-Interceptors.md) system can not work). +* Only `async` methods (methods returning a `Task` or `Task`) are intercepted. So, sync methods can not start a UOW. + +> Notice that if `FooAsync` is called inside a UOW scope, then it already participates to the UOW without needing to the `IUnitOfWorkEnabled` or any other configuration. + +### UnitOfWorkAttribute + +`UnitOfWork` attribute provides much more possibility like enabling or disabling UOW and controlling the transaction behavior. + +`UnitOfWork` attribute can be used for a **class** or a **method** level. + +**Example: Enable UOW for a specific method of a class** + +````csharp +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Uow; + +namespace AbpDemo +{ + public class MyService : ITransientDependency + { + [UnitOfWork] + public virtual async Task FooAsync() + { + //this is a method with a UOW scope + } + + public virtual async Task BarAsync() + { + //this is a method without UOW + } + } +} +```` + +**Example: Enable UOW for all the methods of a class** + +````csharp +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Uow; + +namespace AbpDemo +{ + [UnitOfWork] + public class MyService : ITransientDependency + { + public virtual async Task FooAsync() + { + //this is a method with a UOW scope + } + + public virtual async Task BarAsync() + { + //this is a method with a UOW scope + } + } +} +```` + +Again, the **same rules** are valid here: + +* If you are **not injecting** the service over an interface (like `IMyService`), then the methods of the service must be `virtual` (otherwise, [dynamic proxy / interception](Dynamic-Proxying-Interceptors.md) system can not work). +* Only `async` methods (methods returning a `Task` or `Task`) are intercepted. So, sync methods can not start a UOW. + +#### UnitOfWorkAttribute Properties + +* `IsTransactional` (`bool?`): Used to set whether the UOW should be transactional or not. **Default value is `null`**. if you leave it `null`, it is determined automatically based on the conventions and the configuration. +* `TimeOut` (`int?`): Used to set the timeout value for this UOW. **Default value is `null`** and fallbacks to the default configured value. +* `IsolationLevel` (`IsolationLevel?`): Used to set the [isolation level](https://docs.microsoft.com/en-us/dotnet/api/system.data.isolationlevel) of the database transaction, if the UOW is transactional. +* `IsDisabled` (`bool`): Used to disable the UOW for the current method/class. + +> If a method is called in an ambient UOW scope, then the `UnitOfWork` attribute is ignored and the method participates to the surrounding transaction in any way. + +**Example: Disable UOW for a controller action** + +````csharp +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Uow; + +namespace AbpDemo.Web +{ + public class MyController : AbpController + { + [UnitOfWork(IsDisabled = true)] + public virtual async Task FooAsync() + { + //... + } + } +} +```` \ No newline at end of file