Write better code with the help of steps which are wrapped in a transaction. Available on Nuget here : #.Net Core - https://www.nuget.org/packages/DeepTransactionCore/ #.Net - https://www.nuget.org/packages/DeepTransaction/
dynamic context = new TransactionContext();
context.Name = "Jhonny Cash";
context.Age = 25;
var response = TransactionWorker.Define("Insert and return a person")
.AddStep<AddPersonStep>()
.AddStep<GetPersonStep>()
.Process(context);
A transaction has a collection of steps. Each step can resolve a piece of your code.
The AddPersonStep step can look like this:
public class AddPersonStep : ITransactionStep
{
private string _name;
private int _age;
public void Before(dynamic input)
{
_name = input.Name;
_age = input.Age;
}
public TransactionContext Execute(dynamic input)
{
using (var repo = new ExtraContext())
{
var person = new Person() {Age = _age, Name = _name};
repo.Persons.Add(person);
repo.SaveChanges();
}
return input;
}
}
A step must implement ITransactionStep and will override two methods: (Before and Execute).
As you can see the input and output is dynamic because we must take advantage of this feature and not write boiler plate code.
The workflow for a step is:
- Call
Beforemethod - here you can extract the params for the context and validate the input parameters - Call
Executemethod - which will execute the business logic
- On your solution navigate to package manager console and execute:
Install-Package DeepTransaction - We need to hook with your dependency injection module:
-
Create a new class which will implement
IDependencyResolver:public class RegisterIoc : IDependencyResolver { public TOut Resolve<TOut>() { return Container.Instance.Resolve<TOut>(); } } -
We need to implement Get method with your dependency injection module. In this case the DI module is Unity
-
As a next step we need to register the newly created class to the framework (This would be a good idea to put it into the bootstrap class from your application)
DeepBootstrapper.MapResolver(new RegisterIoc());
-
In case you want reuse your transactions in other transactions it can be done very easy:
public class FirstTransaction : BaseTransaction
{
public FirstTransaction() : base("My Transaction")
{
this.AddStep<Step3>().AddStep<Step4>();
}
}
We must inherit BaseTransaction and in the constructor we can add the steps needed for the transaction.
The usage would look like this (like a normal step):
var response = TransactionWorker.Define("Do a lot of work")
.AddStep<FirstTransaction>()
.AddStep<SecondTransaction>()
.AddStep<Step5>()
.Process(tranContext);
As you can see we can mix transactions with steps.
Because we are using your Dependency Injection module we can use inject on steps different modules to work with:
public class ArchiveStep : ITransactionStep
{
private IZipService _zipService;
private Stream _stream;
public ArchiveStep(IZipService zipService)
{
this._zipService = zipService;
}
public void Before(dynamic input)
{
_stream = input.StreamFile;
}
public TransactionContext Execute(dynamic input)
{
input.ArchivedStream = _zipService.Archive(_stream);
return input;
}
}
If an error occurs then all the database modifications will rollback.