Castle ActiveRecord: TransactionScope - nhibernate

Just a quick question about usage of TransactionScope in ActiveRecord. Is this something that is used and works or do people use some other method of handling transactions. I am not familiar, and I am not working with AC but I am thinking about adopting SessionScope and TransactionScope for my project, and was just wondering what people think about it.

If you can use Windsor, I recommend using the ActiveRecordIntegration facility in combination with the Automatic Transaction Management Facility which allows you to apply transactions declaratively, e.g.:
using Castle.Services.Transaction;
[Transactional]
public class BusinessClass
{
public void Load(int id)
{
...
}
// note the "virtual"
[Transaction(TransactionMode.Requires)]
public virtual void Save(Data data)
{
...
}
}

Related

How to implement Transactions with Generic Repository Pattern?

I am developing a .NET Core application where I leverage the Generic Repository pattern and I would like to know how can I implement a transaction:
IGenericRepository
public interface IGenericRepository<T>
{
Task InsertAsync(T insert);
Task<bool> RemoveAsync(object id);
Task UpdateAsync(T entity);
Task<T> GetByIdAsync(object id,string includeProperties="");
Task<IQueryable<T>> GetAsync(Expression<Func<T, bool>> filter=null,
int? skip=null,
int? take=null,
Func<IQueryable<T>,IOrderedQueryable<T>> orderBy = null,
string includeProperties = "");
Task SaveAsync();
}
I was looking at this implementation which uses UnitOfWork as well, but in .NET Core, I do not have a DbContextTransaction.
I am not using UnitOfWork yet. Currently my service looks like this:
public class SomeService
{
IGenericRepository<A> arepo;
IGenericRepository<B> brepo;
public SomeService(IGenericRepository<A> arepo,IGenericRepository<B> brepo)
{
this.arepo=arepo;
this.brepo=brepo;
}
public async Task DoTransaction(id)
{
var a=await arepo.GeyById(id)
await brepo.RemoveAsync(a.Id);
await brepo.SaveChangesAsync();
await arepo.InsertAsync([something]);
await arepo.SaveChanges();
}
}
I would want to make this transactional and also, avoid using SaveChangesAsync for all repositories that get involved.
What would be a solution?
Well I am not expert in entity framework, but I am answering in terms of repository and unit of work.
To begin with, avoid unnecessary wrapper of additional generic repository as you are already using full-ORM. Please refer to this answer.
but in .NET Core i do not have a DbContextTransaction.
The DbContextTransaction is important but not a key for implementing unit of work in this case. What is important is DBContext. It is DBContext that tracks and flushes the changes. You call SaveChanges on DBContext to notify that you are done.
I would want to make this transactional
I am sure there must be something available to replace DbContextTransaction or to represent transaction.
One way suggested by Microsoft is to use it as below:
context.Database.BeginTransaction()
where context is DbContext.
Other way is explained here.
also ,avoid using SaveChangesAsync for all repos that get involved
That is possible. Do not put SaveChanges in repositories. Put it in separate class. Inject that class in each concrete/generic repository. Finally, simply call SaveChanges once when you are done. For sample code, you can have a look at this question. But, code in that question have a bug which is fixed in the answer I provided to it.

Correct use of the NHibernate Unit Of Work pattern and Ninject

I have the following implementation and would like some feedback as to whether it makes correct use of NHibernate for sessions and transactions.
public interface IUnitOfWork : IDisposable
{
ISession CurrentSession { get; }
void Commit();
void Rollback();
}
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
CurrentSession = _sessionFactory.OpenSession();
_transaction = CurrentSession.BeginTransaction();
}
public ISession CurrentSession { get; private set; }
public void Dispose()
{
CurrentSession.Close();
CurrentSession = null;
}
public void Commit()
{
_transaction.Commit();
}
public void Rollback()
{
if (_transaction.IsActive) _transaction.Rollback();
}
}
Ninject binding
Bind<IUnitOfWork>().To<UnitOfWork>().InTransientScope();
Bind<ISessionFactory>().ToProvider<NHibernateSessionFactoryProvider>().InSingletonScope();
Bind<IRepository>().To<Repository>().InTransientScope();
Here is an example of the usage:
public class Repository : IRepository
{
private readonly ISessionFactory _sessionFactory;
public Repository(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
public void Add(IObj obj)
{
using (var unitOfWork = new UnitOfWork(_sessionFactory))
{
unitOfWork.CurrentSession.Save(obj);
unitOfWork.Commit();
}
}
}
In my previous implementation I would inject IUnitOfWork into my repository constructor like so
public Repository(IUnitOfWork unitOfWork)
{...
But the Dispose() method would not execute causing a subsequent call to throw this exception: "Cannot access a disposed object. Object name: 'AdoTransaction'."
First observation: your repository should not commit the unit of work. This defeats the whole point of the unit of work pattern. By immediately saving your changes inside the repository, you're "micro managing" the NHibernate Session.
The unit of work should be referenced higher up the stack, in your application/service layer. This allows you to have application code that performs several actions, potentially on different repositories, and still at the end commit everything at once.
The UnitOfWork class itself looks Ok, though you should ask yourself if you really need it. In NHibernate, the ISession IS your unit of work. Your UnitOfWork class does not seem to add a lot of value (especially since you're exposing the CurrentSession property anyway)
But you do need to think about it's lifetime. I think you have it wrong on this point. Session lifetime management depends on the type of application you're developing: in a web app, you typically want to have a unit of work per request (you might want to google on 'nhibernate session per request'). In a desktop app it's slightly more complicated, you will most of the time want a 'session per screen' or 'conversation per business transaction'.
I have a mostly CRUD type of application, and I implemented the Unit Of Work with Repository pattern, but couldn't really get away from the Session/Transaction split. Sessions and Transactions need different lifetimes. In the desktop world, a Session is usually "per-screen" and a Transaction is "per-user-action".
More information in this excellent article.
So what I ended up with was:
IUnitOfWork -> Wraps session, implements IDisposable
IAtomicUnitOfWork -> Wraps transaction, implements IDisposable
IRepository -> Provides Get, Save, Delete and query access
I made it so that you need an IUnitOfWork to build an IAtomicUnitOfWork and you need an IAtomicUnitOfWork to build an IRepository, so that enforces proper transaction management. That's really all I gained by implementing my own interfaces.
As jeroenh said, you are almost just as well to use ISession and ITransaction but in the end I felt a little better writing all my code against an interface that I defined.
An important part of the answer lies in what you want your transaction sizes to be. Right now (as jeroenh has indicated) the transaction is per method invocation on your repository. This is very small and probably not needed. I created an ASP.MVC application and it uses a transaction size that included everything from a single http request. This could be multiple database reads/updates. I am using the same unit of work and Ninject for IOC. Take a look, maybe something will help with your issues:
http://bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/
http://bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
http://bobcravens.com/2010/09/the-repository-pattern-part-2/
http://bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/
Hope this helps.
Bob

Using nHibernate and the repository pattern, need some direction

Ok so I 'm just getting into nhibernate (using fluent).
One thing that I love about it is that I can use the Repository pattern (read about it from the nhibernate rhino blog).
Basically using generics, I can create methods that will work accross ALL my database tables.
public interface IRepository<T>
{
T GetById(int id);
ICollection<T> FindAll();
void Add(T entity);
void Remove(T entity);
}
public class Repository<T> : IRepository<T>
{
public ISession Session
{
get
{
return SessionProvider.GetSession();
}
}
public T GetById(int id)
{
return Session.Get<T>(id);
}
public ICollection<T> FindAll()
{
return Session.CreateCriteria(typeof(T)).List<T>();
}
public void Add(T t)
{
Session.Save(t);
}
public void Remove(T t)
{
Session.Delete(t);
}
}
I then inherit the Repository class and I can then add methods that are specific to that entity.
When trying to add an Update method, someone mentioned that the Repository pattern is suppose to act on collections? Am I looking at things incorrectly here? Why can't I create an update method?
I tried adding a update method, but I'm confused as to how I will handle the session and update the database?
I want a single place for all my database access for each entity, so UserRepository will have all basic CRUD and then maybe some other methods like GetUserByEmail() etc.
Don't use the repository pattern - use the UnitOfWork pattern instead, and pass defined query ICriteria to the ISession. Essentially the Repo pattern is wrapping something that doesn't need to be wrapped with NH.
see http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx for more info
Perhaps you misheard or someone mispoke - the Repository pattern is supposed to expose collection like behavior, not operate on collections. Just like you can add, remove and search for items in a collection, your repository offers save, delete and search operations that work against your database.
I suggest you download the code for S#arp Architecture. It includes a repository implementation that you can reuse quite easily. If you don't want to take the dependency, at the very least you can spend some time studying their implementation to give you a better idea of how to approach it yourself.

NHibernate ITransaction and pure domain model

I'm trying to write my Domain Model as persistence-ignorant as possible. The only thing I'm doing right now is marking every property and method virtual, as NHibernate requires that for lazy-loading.
In my domain model assembly I define some repository interfaces:
public interface IRepository<TEntity> where TEntity : EntityBase {
TEntity Get(int id);
/* ... */
}
public interface IProductRepository : IRepository<Product> { ... }
Then I have a data assembly. This one will reference NHibernate, it knows about its existence. This is the assembly that implements those repository interfaces:
public abstract class Repository<TEntity> : IRepository<TEntity> {
public TEntity Get(ind id) { ... }
/* ... */
}
public class ProductRepository : Repository<Product>, IProductRepository {
/* ... */
}
and so on.
Now I wanted to implement a transaction functionality to my repositories. To do so, I would add a BeginTransaction method on my IRepository interface. However, I cannot define its return type as NHibernate.ITransaction, since I want to keep the domain model persistence-ignorant, and not be forced to reference NHibernate's assembly from my domain model assembly.
What would you do?
Would you simply implement a void BeginTransaction(), a void Commit(), and a void RollBack() methods on the interface, and let the repository implementation manage the ITransaction object internally?
Or would you find a way to expose the ITransaction object to let the client manage the transaction directly with it, instead of using repository's methods?
Thanks!
You can take a look at the Sharp Architecture which has already implemented everything you talk about, including generic repositories with transactions support. The solution there is that IRepository has DbContext property which encapsulates transactions (it's actually an interface).
This is the first of the options that you described (custom transactions interface which hides NHibernate). And it works well.
I guess you can even re-use S#arp code regardless if you intend to use the full framework.
IMO Transactions should always start and end in business logic, in other words the transaction should start in the service layer not the repository layer and the repository should enlist it's self in the transaction, ideally this would be done implicitly.
Now if you're using NH then if your service and repositories share the same 'session' (which they should) then you can call 'BeginTransaction' in the service layer and commit or roll back as required:
Eg, imagine this a method on a service:
public void RegisterCustomer(Customer customer)
{
try
{
using(var transaction = _session.BeginTransaction())
{
_customerRepository.Save(customer);
_customerSurveyRepository.Save(customerSurvey);
// DO What ever else you want...
transaction.Commit();
}
}
catch (Exception exn)
{
throw new AMException(FAILED_REGISTRATION, exn);
}
}
How the repositories obtain a reference to the same Session can be solved by injecting in the constructors or by using a the SessionFactory to obtain the current session...

NHibernate Linq uses implicit transaction?

I'm using Ayende's NHibernate Linq version 2.1.2, available here, and when I use NHProf to inspect queries that use this method:
public IQueryable<T> GetAll()
{
return Session.Linq<T>();
}
It gives me the warning that I'm using an implicit transaction. Problem is, I'm using this in a repository to abstract out the database session, but I still want the flexibility of returning an IQueryable so I can run any Linq query I want. Is there a way to explicitly wrap the Session.Linq<T>() in a transaction without exposing it, or should I just ignore the warning in this case?
A little more background. I'm using the method like so:
var repo = new Repository();
var animals = repo.GetAll<Animal>().Where(x => x.Size > 100);
NoahsArk.LargeAnimals.AddRange(animals);
NHProf's message is actually not related to your repository implementation. It's just pointing out that you are running your query outside a transaction, which can be a source of problems.
Ayende explains this in a blog post: NH Prof Alerts: Use of implicit transactions is discouraged
You should manage your transactions from a higher level in your application. There are several ways to do this while using repositories, have a look at unhaddins
I had a very similar problem which I solved quite simply.
I created a LinqClass within my repository returned by my Linq method
public virtual LinqClass Linq()
{
return new LinqClass(Session, LinqSource());
}
public class LinqClass : IDisposable
{
public LinqClass(ISession session, IQueryable<T> linqSource)
{
_linq = linqSource;
_transaction = session.BeginTransaction();
}
private readonly IQueryable<T> _linq;
private readonly ITransaction _transaction;
public IQueryable<T> Linq
{
get { return _linq; }
}
public void Dispose()
{
_transaction.Commit();
}
}
I could then wrap my linq statements up in a using block
using (var linq = Linq())
{
var versions = from t in linq.Linq
where t.BaseName == BaseName
orderby t.Version descending
select t.Version;
return versions.Take(1).SingleOrDefault();
}
and even if returning data from the middle of it, the transaction commit is still called. No more implicit transactions. Obviously this example is for NHibernate, but it should work similarly for other things.
I'm pretty sure you can ingnore this warning.
Can you see the transaction in NHProf?
http://groups.google.com/group/nhprof/browse_thread/thread/fbc97d3286ad783b