Reputation: 8144
I'm looking for some advices about the unit of work pattern.
Is the commit on the unit of work called multiple times or just one time and then leaving the object for garbage collection?
Is it a good idea to inject the unit of work play or should I pass it around in method call when asking objects to perform some work?
Upvotes: 4
Views: 4478
Reputation: 1070
The idea behind a unit of work is encapsulating a 'unit of work' such as all the changes exacted from actions within a single method (ex. add a user with certain roles, the user will be added and the roles associated with the user).
You would use a unit of work to 'batch up' these changes and execute them in one go (usually via a transaction - because the different actions make up one unit of work, if one fails - all should)
So really, you would only call commit once per unit of work. Most ORM/s like entity framework/nhibernate allow you to execute multiple commits via a single unit of work, each associated with a specific transaction representing a unit of work.
Upvotes: 0
Reputation: 172626
Instances of types that implement the unit of work pattern usually have a single owner that needs to control its lifetime. Methods like Commit
, Open
, Close
, and Dispose
are often strong signals that a type should be controlled explicitly (or placed behind an abstraction if appropriate).
For this reason it is better not to inject an unit of work instance itself, but inject a type that knows how to create such unit of work: a factory.
The unit of work in that case functions as a context and when other objects need to perform operations in the same context (to keep the operation atomic for instance) you need to pass it. This might look like this:
public class MyCommand
{
private readonly IUnitOfWorkFactory factory;
public MyCommand(IUnitOfWorkFactory factory)
{
this.factory = factory;
}
public void Execute()
{
using (var context = this.factory.CreateNew())
{
this.DoSomeNiceThings(context);
context.Commit();
}
}
}
Many DI frameworks offer you the possibility of defining a context in which an object and its dependencies run. This allows you to inject the unit of work itself and inject that same instance in all its dependencies. This is a very useful feature, but not something I would do in this particular scenario, because the correctness of your code gets dependant on the way you configure the scope of your unit of work. This makes your code very implicit, hard to follow and easy to break. IMO such feature is especially useful in scenario's were the consumer doesn't care about the dependency. This feature is therefore very useful for performance optimizations, implementing caching strategies and such.
Is the commit on the unit of work called multiple times or just one time and then leaving the object for garbage collection?
Whether calling Commit
multiple times is a valid scenario depends on how you design it. In my production applications, I often run my unit of work inside a transaction, which allows me to commit operations to the database (to get database generated keys for instance) while keeping the business operation atomic.
I hope this helps.
Upvotes: 5