I took a very similar approach. In the HttpModule I ask the sessionfactory for a new session + bind it when a new request comes in. But I also begin the transaction here.
Then when the request is ending I simply unbind it and attempt to commit the transaction.
I took a very similar approach. In the HttpModule I ask the sessionfactory for a new session + bind it when a new request comes in. But I also begin the transaction here.
Then when the request is ending I simply unbind it and attempt to commit the transaction. Also my base repository doesn't take a session in any way - it instead will ask for the current session and then perform some work with the session. Also I don't wrap anything inside this base class with a transaction.
Instead the entire http request is a single unit of work. This might not be appropriate for the project you are working on, but I prefer this approach because each request will fail or succeed as a single atomic unit. I have a full blog post here with source code if you are interested in the actual implementation.
The below is a sample of what this base repository looks like: public abstract class NbernateRepository where T : class { protected readonly ISessionBuilder mSessionBuilder; public NbernateRepository() { mSessionBuilder = SessionBuilderFactory. CurrentBuilder; } public T Retrieve(int id) { ISession session = GetSession(); return session. Get(id); } public void Save(T entity) { ISession session = GetSession(); session.
SaveOrUpdate(entity); } public void Delete(T entity) { ISession session = GetSession(); session. Delete(entity); } public IQueryable RetrieveAll() { ISession session = GetSession(); var query = from Item in session.Linq() select Item; return query; } protected virtual ISession GetSession() { return mSessionBuilder. CurrentSession; } }.
Thanks for the answer! Yes, it's a simple and straightforward way to solve it. But my problem is that I want to make sure that there is a transaction surrounding a repository operation, even if the application service, repository etc is not called by a web request (other types of clients), therefore I wanted to have a transaction surrounding the lowest level (e.g.Session.
Save) and then use TransactionScope to create a longer transaction if needed. But your solution is simple and I like that, mabye I'll use that and then make sure that other clients use transactions aswell.
The transaction lifecycle should be: using (TransactionScope tx = new TransactionScope()) { using (ISession session1 = ...) using (ITransaction tx1 = session. BeginTransaction()) { ...do work with session tx1.Commit(); } using (ISession session2 = ...) using (ITransaction tx2 = session. BeginTransaction()) { ...do work with session tx2.Commit(); } tx.Complete(); }.
You can actually check to see if a transaction is active using: Session.Transaction.IsActive. If one isn't active, you can create one. You could also create a Transact method that does most of this for you automatically.
Here's an excerpt that's mostly from N0 Cookbook: // based on N0 Cookbook, Data Access Layer, pg. 192 public class GenericDataAccessObject : IGenericDataAccessObject { // if you don't want to new up your DAO per Unit-of-work you can // resolve the session at the time it's accessed. Private readonly ISession session; protected GenericDataAccessObject(ISession session) { this.
Session = session; } protected ISession Session { get { return session; } } public virtual T Get(TId id) { return Transact(() => Session. Get(id)); } protected virtual void Save(T entity) { Transact(() => Session. Save(entity)); } /// /// Perform func within a transaction block, creating a new active transaction /// when necessary.No error handling is performed as this function doesn't have /// sufficient information to provide a useful error message.
/// /// The return type /// The function wrapping the db operations /// The results returned by func protected TResult Transact(Func func) { // the null Transaction shouldn't happen in a well-behaving Session // implementation if (Session. Transaction == null ||!Session.Transaction. IsActive) { TResult result; // transaction rollback happens during dispose when necessary using (var tx = Session.
BeginTransaction()) { result = func.Invoke(); tx.Commit(); } return result; // We purposefully don't catch any exceptions as if we were to catch // the error at this point we wouldn't have enough information to describe // to the user why it happened -- we could only describe what happened. } return func.Invoke(); } protected void Transact(Action action) { Transact(() => { action.Invoke(); return false; } ); } }.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.