{"action":"created","issue":{"url":"https://api.github.com/repos/npgsql/npgsql/issues/1208","repository_url":"https://api.github.com/repos/npgsql/npgsql","labels_url":"https://api.github.com/repos/npgsql/npgsql/issues/1208/labels{/name}","comments_url":"https://api.github.com/repos/npgsql/npgsql/issues/1208/comments","events_url":"https://api.github.com/repos/npgsql/npgsql/issues/1208/events","html_url":"https://github.com/npgsql/npgsql/issues/1208","id":166952736,"number":1208,"title":"Transaction exception thrown while processing multiple connection objects (enlist=true).","user":{"login":"warcha","id":19942084,"avatar_url":"https://avatars.githubusercontent.com/u/19942084?v=3","gravatar_id":"","url":"https://api.github.com/users/warcha","html_url":"https://github.com/warcha","followers_url":"https://api.github.com/users/warcha/followers","following_url":"https://api.github.com/users/warcha/following{/other_user}","gists_url":"https://api.github.com/users/warcha/gists{/gist_id}","starred_url":"https://api.github.com/users/warcha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/warcha/subscriptions","organizations_url":"https://api.github.com/users/warcha/orgs","repos_url":"https://api.github.com/users/warcha/repos","events_url":"https://api.github.com/users/warcha/events{/privacy}","received_events_url":"https://api.github.com/users/warcha/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/npgsql/npgsql/labels/bug","name":"bug","color":"e11d21"}],"state":"open","locked":false,"assignee":{"login":"roji","id":1862641,"avatar_url":"https://avatars.githubusercontent.com/u/1862641?v=3","gravatar_id":"","url":"https://api.github.com/users/roji","html_url":"https://github.com/roji","followers_url":"https://api.github.com/users/roji/followers","following_url":"https://api.github.com/users/roji/following{/other_user}","gists_url":"https://api.github.com/users/roji/gists{/gist_id}","starred_url":"https://api.github.com/users/roji/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/roji/subscriptions","organizations_url":"https://api.github.com/users/roji/orgs","repos_url":"https://api.github.com/users/roji/repos","events_url":"https://api.github.com/users/roji/events{/privacy}","received_events_url":"https://api.github.com/users/roji/received_events","type":"User","site_admin":false},"assignees":[{"login":"roji","id":1862641,"avatar_url":"https://avatars.githubusercontent.com/u/1862641?v=3","gravatar_id":"","url":"https://api.github.com/users/roji","html_url":"https://github.com/roji","followers_url":"https://api.github.com/users/roji/followers","following_url":"https://api.github.com/users/roji/following{/other_user}","gists_url":"https://api.github.com/users/roji/gists{/gist_id}","starred_url":"https://api.github.com/users/roji/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/roji/subscriptions","organizations_url":"https://api.github.com/users/roji/orgs","repos_url":"https://api.github.com/users/roji/repos","events_url":"https://api.github.com/users/roji/events{/privacy}","received_events_url":"https://api.github.com/users/roji/received_events","type":"User","site_admin":false}],"milestone":{"url":"https://api.github.com/repos/npgsql/npgsql/milestones/24","html_url":"https://github.com/npgsql/npgsql/milestones/3.2","labels_url":"https://api.github.com/repos/npgsql/npgsql/milestones/24/labels","id":1720681,"number":24,"title":"3.2","description":"","creator":{"login":"roji","id":1862641,"avatar_url":"https://avatars.githubusercontent.com/u/1862641?v=3","gravatar_id":"","url":"https://api.github.com/users/roji","html_url":"https://github.com/roji","followers_url":"https://api.github.com/users/roji/followers","following_url":"https://api.github.com/users/roji/following{/other_user}","gists_url":"https://api.github.com/users/roji/gists{/gist_id}","starred_url":"https://api.github.com/users/roji/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/roji/subscriptions","organizations_url":"https://api.github.com/users/roji/orgs","repos_url":"https://api.github.com/users/roji/repos","events_url":"https://api.github.com/users/roji/events{/privacy}","received_events_url":"https://api.github.com/users/roji/received_events","type":"User","site_admin":false},"open_issues":25,"closed_issues":17,"state":"open","created_at":"2016-04-20T14:56:41Z","updated_at":"2016-08-09T23:04:35Z","due_on":null,"closed_at":null},"comments":8,"created_at":"2016-07-22T01:32:34Z","updated_at":"2016-08-16T16:03:35Z","closed_at":null,"body":"While processing multiple connection objects within a distributed transaction the following exception is thrown:\r\n\r\n_“Unhandled Exception: Npgsql.NpgsqlException: ERROR: prepared transaction with identifier \"\"3fd8cffd-7114-4a1b-a7d3-19e93c0b27d9\"\" does not exist”._\r\n\r\nUpon investigation, I've found that initially this exception is being thrown (and subsequently handled within each connections app domain due to this being a distributed transaction) \r\n\r\n_\"A first chance exception of type 'Npgsql.NpgsqlException' occurred in Npgsql.dll \r\nAdditional information: ERROR: DISCARD ALL cannot run inside a transaction block\"_\r\n\r\nA DISCARD ALL is being executed on the database whilst still in the middle of a transaction resulting in the db server returning the above error. The postgres documentation states: _DISCARD ALL cannot be executed inside a transaction block._\r\n\r\nFollowing the stack trace for this I can see that a ReleaseWithDiscard() method is being called from NpgsqlConnector.ReleaseResources(), it looks like whilst inside a transaction some objects are attempting to clean up and are inadvertently executing a DISCARD ALL.\r\n\r\nThis results in the NPGSQL receiving the server error and as part of handling the server error executes a rollback at the db, in the meantime the remainder of the connection objects are processed and subsequently a Transaction.Complete() is called, however the transaction no longer exists at the db resulting in the transaction does not exist error.\r\n\r\nThere should be an additional check that no ambient transactions exist before a ReleaseWithDiscard() is called.\r\n\r\nI think that the NpgsqlConnector.ReleaseResources() method should be changed as follows to stop a DISCARD ALL being executed whilst inside a transaction:\r\n\r\n```c#\r\ninternal void ReleaseResources()\r\n{\r\n     if (_connection_state != ConnectionState.Closed)\r\n    {\r\n        if (SupportsDiscard && System.Transactions.Transaction.Current == null)\r\n        {\r\n            ReleaseWithDiscard();\r\n        }\r\n            else\r\n        {\r\n            ReleasePlansPortals();\r\n            ReleaseRegisteredListen();\r\n        }\r\n    }\r\n}\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/npgsql/npgsql/issues/comments/240149928","html_url":"https://github.com/npgsql/npgsql/issues/1208#issuecomment-240149928","issue_url":"https://api.github.com/repos/npgsql/npgsql/issues/1208","id":240149928,"user":{"login":"omatrot","id":4366356,"avatar_url":"https://avatars.githubusercontent.com/u/4366356?v=3","gravatar_id":"","url":"https://api.github.com/users/omatrot","html_url":"https://github.com/omatrot","followers_url":"https://api.github.com/users/omatrot/followers","following_url":"https://api.github.com/users/omatrot/following{/other_user}","gists_url":"https://api.github.com/users/omatrot/gists{/gist_id}","starred_url":"https://api.github.com/users/omatrot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/omatrot/subscriptions","organizations_url":"https://api.github.com/users/omatrot/orgs","repos_url":"https://api.github.com/users/omatrot/repos","events_url":"https://api.github.com/users/omatrot/events{/privacy}","received_events_url":"https://api.github.com/users/omatrot/received_events","type":"User","site_admin":false},"created_at":"2016-08-16T16:03:35Z","updated_at":"2016-08-16T16:03:35Z","body":"It is August 16th :)\r\n\r\n@roji No problem\r\n\r\n@warcha There is another potential issue depending on your context. Because everything is asynchronous, the TrasactionCompleted event may be fired while the transaction is being prepared and not yet finished (it could take a while, trust me). So the code has to be synchronized, or you may dispose the connection before it has finished prepared the transaction.\r\n\r\nIn a previous patch on the driver, I've been sleeping 100ms in the TrasactionCompleted event before disposing the EF context. Now The Driver creates an AutoReset Event that has the name of the transaction. This allow the code in the vent to wait for it before disposing the context. This is much safer and faster of course."}}
{"actor":{"display_login":"omatrot"}}