Unit of Work (shared transaction) with DBreeze

Feb 16, 2015 at 10:03 PM
Hi,
First of all, sorry about my English :) (I speak Spanish)
I'm working on a desktop application and I need an embedded database (key-value, etc) so I have chosen DBreeze.

I'm used to work with web applications and layered applications so in my "default" architecture, I use as an standard the Unit of work and Repository Pattern, mixed with EntityFramework. With all of this, I'm trying to say that I'm used to work with one Dbcontext per http request.

In this proyect, I started with my "default" architecture, I thought that I could replace my "dbcontext" with the DBreezeEngine or one Transaction.

The problem with this is that, when I'm trying to use Task based operations, this operations are performed on different threads, so I'm getting the following error: "One transaction can be used from one thread only!" (This became obvious after reading the doc).

So, the question here is, how do you mix layered applications, with different repositories all working on one transaction to ensure that all the information is saved or not.

Maybe I'm considering a wrong architecture, but it is pretty standard (layerd architecture, considering separations of concerns, etc). I can't consider a good "strategy" use "using (... engine.GetTransaction())" on the presentation layer.

The examples on the documentation are good but they are not "real world" examples.
(I think)

Hope I have been clear enough.

Thanks for all!
Federico
Coordinator
Feb 17, 2015 at 8:03 AM
Hi,
Open transaction, make a set of sequential operations mutating one or many database entities, commit and close transaction. This is a real world scenario.
If you want to perform sequential operations (what transaction should be) in different threads, then it's a kind of misunderstanding.

In short words: don't call sequential operations in new threads and using "await" keywords.

Every HTTP request is already run in a new thread from the application point of view. If your web server currently serves 2 parallel HTTP requests then every of them is already running in a new thread.
Inside of a thread there is no necessity to to make another thread which will work with DB. Just use the same thread. Use "using open tran" and don't call any function working with DB in "async" mode.
In async you may call requests to other web services, but better not to make it with sequential operations (that is DB processing).

Create static DBreeze engine instance per server aaplication. In HTTP request use "using open tran" and execute inside the set of sequential operations. Of course, don't call "Task" with "await" inside of transaction (call it before, if you want to acquire remote web service results), but just run functions in sequential mode.
Mar 13, 2015 at 8:18 PM
Sorry that I haven't replied before but I have been a little bit disconnected from the project.
The app that I'm developing is an WPF app, not an web application. In most cases, when you develop an "winform" application, you have to run the code on "background" threads in order to not block the main thread where the UI runs. In other case, the UI will freeze.

"Create static DBreeze engine instance per server application. In HTTP request use "using open tran" and execute inside the set of sequential operations. Of course, don't call "Task" with "await" inside of transaction (call it before, if you want to acquire remote web service results), but just run functions in sequential mode."

That's the behavior that I want to emulate, but the restriction of "one transaction per thread" is not a minor problem in my case.

I will try to find a workaround or change the structure of the repositories or architecture. I understand the restriction of the transaction per thread but it's obvious that's easy to work without this restriction. :)

Thanks for your help.
Coordinator
Mar 13, 2015 at 10:24 PM
For me is very hard to imagine architecture where "one transaction per thread" is a big problem. Even if we use functional, async programming style - there are plenty of suitable solutions. Currently, I don't see the necessity to change subj in DBreeze architecture due to the vision of the fact, that it's possible to work with DBreeze in parallel (when saving into different tables) and to let to execute one transaction in parallel thread is just dangerous.
But, what is really obvious, that code is open ;)