Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EnlistInAmbientTransaction should not change isolation level to SERIALIZABLE if there is no ambient transaction #12

Closed
fschmied opened this issue Aug 20, 2015 · 7 comments
Milestone

Comments

@fschmied
Copy link

When EnlistInAmbientTransaction is called in wire-up, the default isolation level of the SQL Persistence for SQL Server is changed from the database default of READ COMMITTED to SERIALIZABLE. This can and probably should be fixed directly in NEventStore (NEventStore/NEventStore#414), but if it isn't, a workaround should be added in NEventStore.Persistence.SQL because the SQL persistence doesn't work as nicely with the SERIALIZABLE isolation level (we experienced database-level deadlocks with multiple readers/writers), and it's also much less efficient.

Reason for the SERIALIZABLE isolation level: If the TransactionScopeOption.Required is used (via code in PersistenceWireup) without specifying an isolation level, the TransactionScope default isolation level of SERIALIZABLE is used if there is no ambient transaction.

@fschmied
Copy link
Author

Workaround for 5.2.0: Ensure there is an active TransactionScope with ReadCommitted isolation level whenever an NEventStore API is called and EnlistInAmbientTransaction is turned on.

@HAXEN
Copy link

HAXEN commented May 11, 2016

@fschmied Could you provide a simple code example of how this should be done? For me as a novice to understand.

@fschmied
Copy link
Author

@HAXEN Sorry, I missed your question. First, check if you really need EnlistInAmbientTransaction, many CQRS applications will not need this option. If you do, wrap all your calls to IStoreEvents in blocks such as this one:

using (var tx = new TransactionScope (TransactionScopeOption.Required, IsolationLevel.ReadCommitted))
{
  var stream = _eventStore.OpenStream(bucketId, streamId, fromRevision, int.MaxValue);
  tx.Complete();
  return stream;
}

@fschmied
Copy link
Author

(PS: IPersistStreams might also be affected, you'll need to check this yourself.)

@HAXEN
Copy link

HAXEN commented May 30, 2016

My usecase being:

Let's say I have an AggregateRoot representing a country and the key being
'sv' for sweden and 'fr' for france etc...

In order to not having duplicates into the eventstore I figure either
having the streamId = 'sv' and query that before creating a new, or having
a table languages with a primary key on countrycode.

Or

Should I make the system being able to create duplicates and in that case
having the read side "delete" the duplicate with a command? In this case
how is this usually handled regarding feedback to the user?

Being sort of new to CQRS this is not clear to me.

On Mon, May 30, 2016 at 4:47 PM, Fabian Schmied notifications@github.com
wrote:

(PS: IPersistStreams might also be affected, you'll need to check this
yourself.)


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#12 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AAJZ1nXVIHqtk4JqiNeG1bUfrQu2FTe0ks5qGviLgaJpZM4FvBfm
.

@fschmied
Copy link
Author

fschmied commented Jun 2, 2016

@HAXEN I guess this bug report is not the right way to discuss your specific question, better ask at https://groups.google.com/d/forum/dddcqrs for CQRS-speciifc questions or at https://groups.google.com/forum/#!forum/neventstore for NEventStore-related ones.

That said, the OpenStream API in NEventStore allows you to specify "0" as the "minimum revision" when opening a stream. This will create the stream if it doesn't exist, or read it if it does. You can then check whether the StreamRevision is 0. If it is, the stream has just been newly created. If not, it already existed. This should make it quite easy to prevent duplicates based on the stream ID.

@AGiorgetti
Copy link
Member

AGiorgetti commented Apr 8, 2017

If there's no ambiente transaction an 'EnlistInAmbientTransaction' has been called a new TransactionScope with the default ReadCommitted transaction isolation level will be generated

AGiorgetti added a commit that referenced this issue Apr 8, 2017
@AGiorgetti AGiorgetti added this to the v6.0.0 milestone Apr 8, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants