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
New behavior for implicit transactions [DNET483] #470
Comments
Commented by: F.D.Castel (fdcastel) Attached is a patch to implement this suggestion using a new property: ImplicitTransactionBehavior (in FbCommand) The default behavior is CommitOnExecute, to keep backward compatibility. This is not the ideal, since it won't fix the problem with ORMs (or any code using System.Data.Common). The default should be CommitOnDispose, but this could be changed in a next "bigger" release (3.1 or 4.0) In this patch there is also some performance tests (not actual tests, should not be commited into /trunk) only to show the difference between the two behaviors: ImplicitTransaction_CommitOnExecute: 100000 commands in 17,949 seconds; 5571,34102178394 commands per second Even with CommitOnDispose as the default behavior, all current unit tests run successfully. Two considerations: 1) In ICloneable.Clone() there is a duplicate assignment of UpdatedRowSource. Is it necessary? 2) In Release() I've kept the rollback for backward compatibility only. I believe it could be always a commit, in both cases. |
Modified by: F.D.Castel (fdcastel)Attachment: DNET483-FDCastel-Proposal.patch [ 12279 ] |
Commented by: @cincuranet This is not going to happen. This behavior is standard in whole http://ADO.NET world (and not only there), and any provider is expected to behave like this. The ORMs handle transactions, very often, per unit-of-work (when pushing it to database), and you can (should) use TransactionScope (or custom tx handling depending on ORM) if you need more control. Getting EF model is done using one command (but fairly huge), so there's actually sequence of starting implicit transaction, executing command and committing. But because the command is huge (takes a time to execute, especially because FB's optimizer isn't that good in this case) and it's loading huge amount of data (FB's wire protocol isn't that succinct as it could be (and there's still room for improvement on client side as well)). |
Commented by: F.D.Castel (fdcastel) You're right. I did the same test with SqlServer and using implicit transaction is (marginally) slower. * Using implicit transaction: * Using explicit transaction: So, my suggestion was a bad call. The current implementation follow the http://ADO.NET guidelines for providers and must be kept. Thank you very much for the pointers! |
Submitted by: F.D.Castel (fdcastel)
Attachments:
DNET-483-FDCastel-Proposal.patch
In the current implementation implicit transactions are being commited after each command execution (and restarted again on the next one). This is not the ideal since it causes a lot of overhead in Firebird.
Of course, with Firebird, the best practice IS to use explicit transactions. So, at first look, this is not a big problem.
However, in db-agnostic scenarios like ORMs the code is often NOT aware of this and expect to use DbCommands without transactions. So, in this case, they are taking a lot of time and server resources.
E.g.: It took me about 20 minutes to reverse engineer some moderately sized (400 tables) Firebird database into Entity Framework. At first I though it was EF fault, but after seeing the performance problems described in DNET280 i did realize that was actually the provider fault.
Given all that, I propose to change the current behavior from "one commit after each execute" to "one commit after FbCommand disposal" when using implicit transactions. This could bring some breaks in compatibility, but it will bring the performance near to levels similar to the other providers.
The text was updated successfully, but these errors were encountered: