Application Architecture - Transactions with RavenDB

I will implement RavenDB in the project and after a few days trying the database, I will now structure this application, but I have a question.

I write business layers for each object (almost), and I have a unique repository class that handles requests and a DocumentStore. I am confused about how I should share a DocumentStore by service level and process transactions.

I am showing an example where I am trying to save and read a document in one transaction.

Repository example:

public class RavenRepository { private static DocumentStore _store; private IDocumentSession _session; public RavenRepository(DocumentStore store) { _store = (_store==null) ? new DocumentStore() { Url = "http://wsk-gcardoso:8081" } : store; } public T SingleOrDefault<T>(Func<T, bool> predicate) where T : BaseModel { using (var session = _store.OpenSession()) { return session.Query<T>().SingleOrDefault(predicate); } } public T Add<T>(T item) where T : BaseModel { using (var session = _store.OpenSession()) { session.Advanced.AllowNonAuthoritiveInformation = this.AllowNonAuthoritiveInformation; session.Store(item); session.SaveChanges(); } return item; } public void Initialize() { _store.Initialize(); } public void Dispose() { _store.Dispose(); } } 

The business layer will look like this:

 public class NewsletterBusiness { private RavenRepository repository; public NewsletterBusiness(RavenRepository ravenRepository) { repository = (ravenRepository == null) ? RavenRepository(null) : ravenRepository; } public Newsletter Add(Newsletter newsletter) { Newsletter news = repository.Add(newsletter); return news; } public Newsletter GetById(long Id) { Newsletter news = repository.SingleOrDefault<Newsletter>(x => x.Id == Id); return news; } } 

Now I am trying to save and read an object (newsletters) in the same transaction. From what I read, I need to set the AllowNonAuthoritativeInformation of the Store document to false in order to wait for the transaction to complete. But due to the fact that I deal with layers and repository, can I store and request db in one transaction?

To be honest, I think I got confused in OpenSession method. I think I messed up the transaction session.

For example, this code:

 var repository = new RavenRepository(null); newsletterBusiness = new NewsletterBusiness(repository); repository.Initialize(); using (var tx = new TransactionScope()) { Newsletter new = newsletterBusiness.Add(new Newsletter { Title = "Created by Tests", Content = "Created By Tests" }); Newsletter objectCreated = newsletterBusiness.GetById(new.Id); repository.Dispose(); tx.Complete(); } 

If I create a second business layer (for example, for images) and I set pictureBusiness.repository = repository (the same RavenRepository object set for businessLayer), will I work in the same newsletterBusiness.repository session?

 picturesBusiness = new PicturesBusiness(repository); Picture pic = picturesBusiness.GetById(20); 

I am very grateful for the help in this matter, Greetings from Portugal!

+4
source share
2 answers

You are not using RavenDB correctly, so you are facing this problem. You can think of a session as a database connection. In your model, you create a separate session for each type. But there really is no real reason why you want to do this.

In fact, you do not want to do this, because a session is perfectly capable of handling several types at once. Moreover, what you have done actually reduces the chances of a session to optimize things like sending updates in one batch to the server.

If you want to have a transactional record that spans types, given your architecture, you will have to use DTC because every other session is a different database connection. If you used the Session per Request model, you will only have one session and you will have transactional semantics by simply calling SaveChanges () once.

+13
source

You are trying to abstract a raven session (which is basically UnitOfWork) using a repository template.

I offer you the following approach: create a UnitOfWork abstraction that will encapsulate the ravenDB session and instantiate the repositories. Here's some pseudo code:

 public class RavenUnitOfWork { private IDocumentSession m_session; public UnitOfWork() { // initialize m_session here } public Repository<T> GetRepository() { return new Repository<T>(m_session); } public void Commit() { m_session.SaveChanges(); } } public class RavenRepository<T> { public Repository(IDocumentSession session) { // Store the session } public T Load(string id) {...} public void Store(T entity) {...} public void Delete(T entity) {...} public IQueryable<T> Query() {...} } 

Here you explicitly implement these patterns.

PS: Of course, you can declare IUnitOfWork and IRepository to your liking ...

+2
source

All Articles