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

Fix | Default SqlCommand's transaction to owning SqlConnection's local transaction #330

Closed
wants to merge 20 commits into from

Conversation

cheenamalhotra
Copy link
Member

@cheenamalhotra cheenamalhotra commented Nov 25, 2019

Hi @CodeAngry

Opening PR from your branch to engage reviewers and understand changes better!
You may continue to work on the same branch while you receive reviews/feedback.

Fixes #28

CodeAngry added 12 commits November 23, 2019 16:18
Made a small change in SqlInternalTransaction's pre-BeginTransaction() validation.
…er after removing tests that became irrelevant.
…on validation against zombied Transactions to throw.

Also changed SqlConnection.CurrentTransaction to return null for zombied Transactions.
…aking a test fail.

It made user/pass empty and removed integrated security breaking login.
Changed it to respect integrated security from the input connection string builder.
…it succeeded.

The value inserted is actually '2000-12-31', checked in unencrypted table.
Noticed in the SqlParameter a .CoercedValue that was 2000/12/31 so that's why it inserts the value.
Changed this value to '0/12/32' for it to actually fail.
…Transaction) and external (vial TSQL) overlapped transactions.
@cheenamalhotra
Copy link
Member Author

@CodeAngry please address failing builds from logs by making necessary changes. Thanks!

@CodeAngry
Copy link

Thank you! I'll finalize all things by tomorrow.

PS: I forgot it's older C# language version. I use default without default(Type) or just null. That seems to fail some tests. I'll edit that tomorrow early.

CodeAngry added 2 commits November 26, 2019 00:56
…testing.

Even if I find this useful, it could be added later on if/when necessary.
CodeAngry added 2 commits November 26, 2019 02:56
Fixed a forgotten netfx block code that only had effect before the change.
Also moved a check in a netcore function few lines up to reduce pointless initializations if we throw.
I don't have anything Azure related.
Copy link
Contributor

@saurabh500 saurabh500 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove SqlBulkCopy.cs from this change and keep it limited to SqlCommand. How to do this. Checkout the SqlBulkCopy.cs from the master branch of dotnet/Sqlclient.

@@ -376,14 +373,6 @@ private SqlCommand(SqlCommand from) : this()
}
}

// Check to see if the currently set transaction has completed. If so,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Behavior change. I have a command lying around and the transaction was changed for the command. Now I associate the new connection with it, and it magically overwrote previous transaction.

Can we stick to the lowest common denominator on how this convenience of deriving the transaction for this command is going to work, while preserving most of the old behavior ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saurabh500 Behavior change. I have a command lying around and the transaction was changed for the command. Now I associate the new connection with it, and it magically overwrote previous transaction.

Since a transaction's lifetime is BeginTransaction - Commit/Rollback/throw, and a single connection has a single active transaction, how can a command be lying around with a different transaction that magically changes? If it had a different transaction reference associated, and the connection ran another transaction, then it's a complete transaction which used to be nullified internally in the old functionality too.

If you associate a new connection to it, you don't do it in the hopes of keeping the old transaction on the .Transaction property and a different connection in the .Connection. This would not have passed validation previously also.

A few lines of code explaining this behavior would be helpful.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saurabh500

Could you provide a few lines of code to verify how these code changes would break?

CodeAngry added 2 commits November 26, 2019 13:27
Also removed my SqlBulkCopy tests.
…ails on Azure but works locally.

Have no experience in TransactionScope, I'll just remove it and someone else can add something if needed.
@CodeAngry
Copy link

I've done all I can on my side. It's out of my hands now. I'll personally use this changed version in my projects from now. It's nice that @roji and the npgsql team got this right the first time. I've added several tests, I don't see how this changes can affect existing code in any way, given how connections, transactions and commands relate to each other and their lifespans.

Also, the SqlBulkCopy change is reverted, even if I'm very not happy with this. Also my tests for that change are removed.

I'm open to any questions but if someone says this breaks backward compatibility, it should be accompanied by a few actual lines of code showcasing the issue.

@CodeAngry
Copy link

So, it'a been a while...

@abatishchev
Copy link

Any update on this, please?

Making the project open source and not accepting changes for months (and years) makes Microsoft's open source commitment just a demagogy.

/cc @yorek, I saw your recent post about this project being open sourced and recently released.

@CodeAngry
Copy link

@abatishchev I'm done here. I'm not even trying to get this in. If they want it, they have it here. Imagine having this dangling but complete for 1 year. Where else but with Microsoft could that fly? If my devs left something done hanging for 1 year I'd fire them all.

Almost one year ago when this was complete, it passed all tests. Not I see it has conflicts. Code changes were trivial at best but 0 **** were given. One MS dev could have wrapped this up in 15mins considering I made the changes with 0 prior knowledge of the code base or GIT.

I personally quit bothering them. They are TOO busy. Maybe in 20 years something might change. Who knows?!

@cheenamalhotra
Copy link
Member Author

Hi @abatishchev @CodeAngry

Please accept our apologies for not getting this addressed soon. We were held upon an unresolved comment above (#330 (comment)) that seemed like a backward compatibility concern, but I believe we need to resume testing this again thoroughly for any possible breaking changes.

Would you be able to resolve conflicts that came in recently, please? while we resume review.

Copy link
Contributor

@DavoudEshtehari DavoudEshtehari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I know you suggest this change a while ago, one of the added features is EventSource, it is required to add some lines to cover logging. You can follow the recent code pattern to discover it.
  • Also, by the purpose of running manual tests on Azure SQL Server, we create a unique table instead of temporary tables by using DataTestUtility.GetUniqueNameForSqlServer.
  • You can use DataTestUtility.ConnectionStrings to cover all variants of a connection string.
  • Remove all unused namespaces and parameters just for a neat code.

@yorek
Copy link

yorek commented Jun 23, 2020

@CodeAngry , @abatishchev I'm very sorry for what happened, and definitely we need to make this right. I asked our engineering team to take a look at this, and I see that they already responded. We are absolutely serious about open source commitment: for how bad this may look, please do not assume this is the norm. Actually many PR has been submitted and accepted. So, we can do better? For sure. Should be judged by just one mistake? Hopefully not :) Thanks, a looking forward to see your work included in SqlClient!

{
var csb = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString)
{
MultipleActiveResultSets = false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your change has affected the MARS behavior. Please, add more test units to cover it.

if (value is null)
{
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that a null value here wouldn't matter as the command will just use the connection's transaction. But since this setter is validating the input, shouldn't null also throw? A user assigning null to this Transaction property will think the command will execute under that transaction, which they believe to be null.

@JRahnama
Copy link
Contributor

JRahnama commented Jul 12, 2020

@CodeAngry we have been waiting for your response to address the comments and concerns. Please update the PR. If the PR is not updated a parallel PR will close this one.

@JRahnama
Copy link
Contributor

Looks like there is conflict in ValidateOverlapTransactionTSqlApi test when MARS is set to true with multiple batches. Needs more investigation.

@initram
Copy link

initram commented Sep 17, 2020

If the PR is not updated a parallel PR will close this one.

Is a parallel PR being worked on or planned, or is this just a hope that a parallel PR will be submitted by someone?

@cheenamalhotra
Copy link
Member Author

Hi @initram

We were waiting for @CodeAngry to update the PR, as there are quite a many feedback comments waiting resolution.

As of now, our team is occupied with other priority activities, but it is in our backlog.
We'll take over this PR as and when time permits.

@CodeAngry
Copy link

Don't wait for me. I don't work in year or 6mo increments. As I said, any MS developer that's slightly intimate with this library can fix this in 15minutes with a coffee break. I can't!... wait months to anything.

Anyone who wants a fix for this is to never use MARS, SqlTransaction, Scoped Transaction and always use SET TRANSACTION ISOLATION LEVEL + BEGIN TRANSACTION + COMMIT/ROLLBACK directly in the SqlConnection. This helps you never have to worry about dragging this useless SqlCommand.Transaction variable around when creating SqlCommands.

If you want just create a IDisposable class that implements the above steps.

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

Successfully merging this pull request may close these issues.

SqlConnection.CreateCommand() - Auto-Enlist in Pending Local Transaction
9 participants