Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Add System.Transactions to corefx #10089

Merged
merged 4 commits into from
Jul 19, 2016
Merged

Conversation

stephentoub
Copy link
Member

This ports System.Transactions from desktop to corefx.

  • Two main pieces were omitted: COM+/EnterpriseServices integration, and DTC support via OleTx. Those have been stubbed out in helpers that throw PlatformNotSupportedException if used.
  • All of the Mono tests were ported, as were some of the desktop tests.

There is still more work to be done before this can be considered stable, e.g. adding more tests (in part to help verify behavior remains the same across the port), working through if/how to add built-in distributed transaction support, etc., but this is a good start and should be sufficient to primary use cases around TransactionScope.

cc: @danmosemsft, @jimcarley, @dmetzgar, @SriniBanala, @EricaMo, @DamianEdwards
Fixes https://github.com/dotnet/corefx/issues/2949

@stephentoub
Copy link
Member Author

stephentoub commented Jul 18, 2016

@jimcarley, please let me know if you have any changes you'd like to see made before this is merged, or whether you're ok with this being merged as-is. Thanks!

@ericstj, could you confirm (or deny :) I've done the packaging correctly?

public System.Guid PromoterType { get; }
public System.Transactions.TransactionInformation TransactionInformation { get { return default(System.Transactions.TransactionInformation); } }
public event System.Transactions.TransactionCompletedEventHandler TransactionCompleted { add { } remove { } }
//protected System.IAsyncResult BeginCommitInternal(System.AsyncCallback callback) { return default(System.IAsyncResult); }

Choose a reason for hiding this comment

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

protected System.IAsyncResult BeginCommitInternal [](start = 10, length = 49)

Is the standard for .NET Core to stick with Task or should we continue to use Begin/End?

Copy link
Member Author

@stephentoub stephentoub Jul 18, 2016

Choose a reason for hiding this comment

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

Sorry, I should have added a comment here.

Originally for .NET Core, we were exluciding the Begin/End methods in favor of including the Task methods. As part of bringing back lots of APIs, we're bringing back those Begin/End methods that were excluded. I did not remove any such APIs as part of the port.

However, that's not why these are commented out. These are actually part of the Mono APIs, even though they're not in the desktop implementation of System.Transactions. It's unclear to me why such "Internal" methods are exposed as protected in Mono, maybe it's a mistake, or maybe it's there for some corner-case scenario that was desired. In any event, I wasn't sure what to do with them contract-wise, so I left them here but commented out. I'll add a comment explaining.

@dmetzgar
Copy link

:shipit:

@jimcarley
Copy link
Member

Stephen,

While I haven’t looked at all of the code, yet, I haven’t seen anything glaring that would prevent this pull request.

I have seen at least one flaw in the ported Mono tests in IntResourceManager.cs and EnlistTest.cs. The return code from Transaction.EnlistPromotableSinglePhase is not really handled correctly. There is no check that EnlistPromotableSinglePhase returns “false” if there is already a PSPE or durable enlistment on the transaction. In the cases where 2 PSPE enlistments are attempted or a Durable followed by a PSPE, there is a check to ensure that there were no enlistment “failures”. This check is based on exceptions being thrown. But a “false” return value from Transaction.EnlistPromotableSinglePhase indicates that the PSPE enlistment could not be created. It isn’t really a “failure”, and thus no exception is thrown. The “false” is an indication that the PSPE enlistment was not possible, but a durable enlistment could be successful and that the caller should attempt such an enlistment.

The above is not necessarily something that needs to be fixed right now. I just wanted to call it out.

Jim

From: Stephen Toub [mailto:notifications@github.com]
Sent: Monday, July 18, 2016 7:52 AM
To: dotnet/corefx corefx@noreply.github.com
Cc: Jim Carley jcarley@microsoft.com; Mention mention@noreply.github.com
Subject: Re: [dotnet/corefx] Add System.Transactions to corefx (#10089)

@jimcarleyhttps://github.com/jimcarley, please let me know if you have any changes you'd like to see made before this is merged, or whether you're ok with this being merged as-is. Thanks!

@ericstjhttps://github.com/ericstj, could you confirm I've done the packaging correctly?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHubhttps://github.com//pull/10089#issuecomment-233351735, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AMw2-NFXKCMxC_cIO2fvKTXRS1ZTPo1Nks5qW5L5gaJpZM4JNjk8.


if (Type == ResourceManagerType.Promotable)
{
_transaction.EnlistPromotableSinglePhase(new PromotableSinglePhaseNotification(this));
Copy link
Member

Choose a reason for hiding this comment

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

EnlistPromotableSinglePhase will not throw an exception if there is already another PSPE or a DurableEnlistment. Instead, it returns false. Right now the tests that exercise these scenarios do not take this into account. This scenario should be taken into account to correctly test EnlistPromotableSinglePhase. One option is to count a "false" return as an enlistment failure.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, so I should basically add an Assert.True around all calls to enlistPromotableSinglePhase that are supposed to succeed? Assuming yes, I'll do that, and if any then cause failures, I'll undo it and add a TODO for follow-up.

Copy link
Member

Choose a reason for hiding this comment

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

No. There are a couple of tests that will induce this to return false, so an Assert.True will break those tests. I think a check for "false" is in order and the "failure" should be counted and verified by the two tests that do this.


In reply to: 71283510 [](ancestors = 71283510)

@jimcarley
Copy link
Member

// stupid.

Please change this to "Don't allow anything that is not supported."


Refers to: src/System.Transactions/src/System/Transactions/TransactionState.cs:5016 in 0f0da74. [](commit_id = 0f0da74, deletion_comment = False)

// that it will be properly released.
internal sealed class SafeIUnknown : SafeHandle
{
private SafeIUnknown() : base(IntPtr.Zero, true) { }
Copy link
Member

Choose a reason for hiding this comment

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

private [](start = 8, length = 7)

Why did you make this private? In the desktop code, this is internal, just like the other constructor.

Copy link
Member Author

Choose a reason for hiding this comment

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

Initially I made it private because nothing was using this ctor to instantiate it; the parameterless ctor was only necessary for the P/Invokes that were creating it, and for that purpose private is fine.

But then I subsequently removed all of those P/Invokes, and now nothing is using this type at all, so I'll just remove the file entirely.

@stephentoub
Copy link
Member Author

Please change this

Will do.

}
}

internal Transaction(DistributedTransaction oleTransaction)
Copy link
Member

Choose a reason for hiding this comment

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

oleTransaction [](start = 52, length = 14)

change the name of this parameter to something like "distributedTransaction"

@jimcarley
Copy link
Member

:shipit:

This is the vast majority of the implementation, ported to corefx.  The main impact is the reliance on OLE has been removed, as has the reliance on COM+.  Distributed transactions aren't supported implicitly, but they can be supported via plugging in a non-MSDTC manager via the relevant interfaces.
This ports all of the Mono System.Transactions tests as well as some of the .NET Framework tests.  There is plenty more cleanup that can be done; I primarily focused on porting them to xunit.
@stephentoub
Copy link
Member Author

Thanks for all the feedback. I've addressed the issues and will merge once the CI build completes.

And fix project.json versions
@karelz karelz modified the milestone: 1.2.0 Dec 3, 2016
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
Add System.Transactions to corefx

Commit migrated from dotnet/corefx@af0f5f1
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
5 participants