4

Is it possible to open a TransactionScope, run a load of async Tasks which operate on an EF4 ObjectContext, and then commit the result?

How is the current transaction scope inferred in EF4? Will this fail if/when a task gets scheduled on a different thread to the transaction scope?

Lawrence Wagerfield
  • 6,471
  • 5
  • 42
  • 84

2 Answers2

4

Yes, it is. For starters, Entity Framework just uses a provider underneath (by default System.Data.SqlClient) which will pick up the "ambient" transaction context from the thread that is executing. So, from there, the only trick is propagating the single transaction to the Tasks you spin up. I have explained how you can do that here in this post.

While that post was more about propgating to PLINQ spawned tasks, the same approach is applicable if you're manually spinning up your own Tasks. If you would like a code sample, please give me basic details of exactly how your Task spawning would work so I can give good example code.

Community
  • 1
  • 1
Drew Marsh
  • 33,111
  • 3
  • 82
  • 100
0

No, you cannot (usefully) do this.

Although Drew Marsh's answer is correct (that there exist means to make the transaction cross thread boundaries), it's not going to help you. ObjectContext is not thread safe - you should not be accessing it from other threads, and you should definitely not be updating it on other threads; you'll have undefined behaviour: you'll probably encounter data-corruption, which (if you're lucky) will cause crashes.

If you want multi-thread ObjectContext access, you'll need to manually serialize the accesses for example using locks. But if you do that, you might as well simply access the context from one thread; it's usually simpler and almost always faster - and then you'll have no issues with your transactions.

If you insist on manually synchronizing access to the ObjectContext rather than using a thread, you could also use a plain CommittableTransaction and pass that along explicity rather than using the ambient transaction; since you'll need to manually control the transaction anyhow, it's clearer to do so with the explicit handle of an object rather than tricky state-transitions (where the exact details of which thread runs what are vital but not explicit in the code).

By the way, if you do use the ambient transaction, I'd be careful with task scheduling, especially with C# 5's async feature, as you may need to be clearly aware of when execution can change thread (I've never tried this, so I can't give you any pointers, unfortunately).

Summary: just don't do this: you're not gaining concurrency by multithreading due to ObjectContext (and in practice, DB) limitations, so you might as well leave one transaction on one thread and keep it simple. Future maintainers will thank you for the clarity.

Eamon Nerbonne
  • 47,023
  • 20
  • 101
  • 166