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

EF5: Avoid deadlocks by connection reusage and allow usage of CreateDatabaseIfNotExists DB initializer [DNET524] #505

Closed
firebird-automations opened this issue Oct 11, 2013 · 9 comments

Comments

@firebird-automations
Copy link

Submitted by: Mark Junker (fubar-coder)

Attachments:
DNET-524-0001.patch
UnitTests.patch

1. Avoid deadlocks by connection reusage:
- Assume that you have both an IDbSet<T1> and IDbSet<T2>
- Use a TransactionScope()
- Create the DbContext
- Create an instance of T1 where you initialize a property T1.X with an instance of T2 queried from the IDbSet<T2>
- Add the instance of T1 to the IDbSet<T1>
- Call SaveChanges()
- Results in a no wait lock because:
- Adding the instance of T1 partially loads the IDbSet<T1> and therefore creates a lock on the table
- SaveChanges() reopens the existing connection which produces a new FbConnectionInternal which tries to write something to a locked table
- Solution: Reuse the internal connection when the FbConnection gets reopened
2. Allow usage of CreateDatabaseIfNotExists DB initializer
- There's a call to context.Database.Exists() while a new TransactionScope(TransactionScopeOption.Suppress) is active
- Solution: Allow Enlist without an active transaction

@firebird-automations
Copy link
Author

Commented by: Mark Junker (fubar-coder)

Fix description

@firebird-automations
Copy link
Author

Modified by: Mark Junker (fubar-coder)

description: #⁠ Avoid deadlocks by connection reusage:
#⁠* Assume that you have both an IDbSet<T1> and IDbSet<T2>
#⁠* Use a TransactionScope()
#⁠* Create the DbContext
#⁠* Create an instance of T1 where you initialize a property T1.X with an instance of T2 queried from the IDbSet<T2>
#⁠* Add the instance of T1 to the IDbSet<T1>
#⁠* Call SaveChanges()
#⁠* Results in a no wait lock because:
#⁠** Adding the instance of T1 partially loads the IDbSet<T1> and therefore creates a lock on the table
#⁠** SaveChanges() reopens the existing connection which produces a new FbConnectionInternal which tries to write something to a locked table
#⁠* Solution: Reuse the internal connection when the FbConnection gets reopened
#⁠ Allow usage of CreateDatabaseIfNotExists DB initializer
#⁠* There's a call to context.Database.Exists() while a new TransactionScope(TransactionScopeOption.Suppress) is active
#⁠* Solution: Allow Enlist without an active transaction

=>

1. Avoid deadlocks by connection reusage:
- Assume that you have both an IDbSet<T1> and IDbSet<T2>
- Use a TransactionScope()
- Create the DbContext
- Create an instance of T1 where you initialize a property T1.X with an instance of T2 queried from the IDbSet<T2>
- Add the instance of T1 to the IDbSet<T1>
- Call SaveChanges()
- Results in a no wait lock because:
- Adding the instance of T1 partially loads the IDbSet<T1> and therefore creates a lock on the table
- SaveChanges() reopens the existing connection which produces a new FbConnectionInternal which tries to write something to a locked table
- Solution: Reuse the internal connection when the FbConnection gets reopened
2. Allow usage of CreateDatabaseIfNotExists DB initializer
- There's a call to context.Database.Exists() while a new TransactionScope(TransactionScopeOption.Suppress) is active
- Solution: Allow Enlist without an active transaction

@firebird-automations
Copy link
Author

Commented by: Mark Junker (fubar-coder)

Patch to test this new feature

@firebird-automations
Copy link
Author

Modified by: Mark Junker (fubar-coder)

Attachment: DNET524-0001.patch [ 12380 ]

@firebird-automations
Copy link
Author

Commented by: @cincuranet

Post a code that shows the behavior, preferably as a test.

@firebird-automations
Copy link
Author

Commented by: Mark Junker (fubar-coder)

The requested unit tests. BTW: EfTransactionTest.EfTransactionScope is expected to fail due to the manual "Enlist" command line handling

@firebird-automations
Copy link
Author

Modified by: Mark Junker (fubar-coder)

Attachment: UnitTests.patch [ 12381 ]

@firebird-automations
Copy link
Author

Commented by: Ben Priebe (benpriebe)

I'd like to +1 this change.

I've tried applying your patch on top of 4.0.0.0 but am having no luck.

Can anyone point me to instructions on how to apply this patch on top of the latest code in sourceforge - https://sourceforge.net/p/firebird/NETProvider/ci/master/tree/

My attempts of runing > git apply DNET524-0001.patch fail and I am assuming the patch is against a different version.

@firebird-automations
Copy link
Author

Modified by: @cincuranet

status: Open [ 1 ] => Closed [ 6 ]

resolution: Incomplete [ 4 ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants