diff options
5 files changed, 48 insertions, 20 deletions
diff --git a/projecttemplates/RelyingPartyLogic/Database.cs b/projecttemplates/RelyingPartyLogic/Database.cs index 9ef72eb..d7efeac 100644 --- a/projecttemplates/RelyingPartyLogic/Database.cs +++ b/projecttemplates/RelyingPartyLogic/Database.cs @@ -8,6 +8,7 @@ namespace RelyingPartyLogic { using System; using System.Collections.Generic; using System.Data; + using System.Data.EntityClient; using System.Data.SqlClient; using System.Linq; using System.ServiceModel; @@ -51,7 +52,7 @@ namespace RelyingPartyLogic { throw; } - DataContextTransaction = dataContext.Connection.BeginTransaction(); + DataContextTransaction = (EntityTransaction)dataContext.Connection.BeginTransaction(); DataContextSimple = dataContext; } @@ -59,14 +60,21 @@ namespace RelyingPartyLogic { } } - internal static IDbTransaction DataContextTransaction { + /// <summary> + /// Gets a value indicating whether the data context is already initialized. + /// </summary> + internal static bool IsDataContextInitialized { + get { return DataContextSimple != null; } + } + + internal static EntityTransaction DataContextTransaction { get { if (HttpContext.Current != null) { - return HttpContext.Current.Items[DataContextTransactionKey] as IDbTransaction; + return HttpContext.Current.Items[DataContextTransactionKey] as EntityTransaction; } else if (OperationContext.Current != null) { object data; if (OperationContext.Current.IncomingMessageProperties.TryGetValue(DataContextTransactionKey, out data)) { - return data as IDbTransaction; + return data as EntityTransaction; } else { return null; } diff --git a/projecttemplates/RelyingPartyLogic/Model.cs b/projecttemplates/RelyingPartyLogic/Model.cs index 10c1518..ca87c90 100644 --- a/projecttemplates/RelyingPartyLogic/Model.cs +++ b/projecttemplates/RelyingPartyLogic/Model.cs @@ -18,15 +18,17 @@ namespace RelyingPartyLogic { /// <summary> /// Clears the expired nonces. /// </summary> - internal void ClearExpiredNonces() { - this.ExecuteCommand("ClearExpiredNonces"); + /// <param name="transaction">The transaction to use, if any.</param> + internal void ClearExpiredNonces(EntityTransaction transaction) { + this.ExecuteCommand(transaction, "DatabaseEntities.ClearExpiredNonces"); } /// <summary> /// Clears the expired associations. /// </summary> - internal void ClearExpiredAssociations() { - this.ExecuteCommand("ClearExpiredAssociations"); + /// <param name="transaction">The transaction to use, if any.</param> + internal void ClearExpiredAssociations(EntityTransaction transaction) { + this.ExecuteCommand(transaction, "DatabaseEntities.ClearExpiredAssociations"); } } } diff --git a/projecttemplates/RelyingPartyLogic/NonceDbStore.cs b/projecttemplates/RelyingPartyLogic/NonceDbStore.cs index 2f3c670..951bf0f 100644 --- a/projecttemplates/RelyingPartyLogic/NonceDbStore.cs +++ b/projecttemplates/RelyingPartyLogic/NonceDbStore.cs @@ -9,6 +9,7 @@ namespace RelyingPartyLogic { using System.Collections.Generic; using System.Data; using System.Data.Common; + using System.Data.EntityClient; using System.Linq; using System.Text; using DotNetOpenAuth.Configuration; @@ -90,7 +91,7 @@ namespace RelyingPartyLogic { private static void ClearNoncesIfAppropriate() { if (++nonceClearingCounter % NonceClearingInterval == 0) { using (var dataContext = new TransactedDatabaseEntities(IsolationLevel.ReadCommitted)) { - dataContext.ClearExpiredNonces(); + dataContext.ClearExpiredNonces(dataContext.Transaction); } } } @@ -100,27 +101,27 @@ namespace RelyingPartyLogic { /// </summary> protected class TransactedDatabaseEntities : DatabaseEntities { /// <summary> - /// The transaction for this data context. - /// </summary> - private DbTransaction transaction; - - /// <summary> /// Initializes a new instance of the <see cref="TransactedDatabaseEntities"/> class. /// </summary> /// <param name="isolationLevel">The isolation level.</param> public TransactedDatabaseEntities(IsolationLevel isolationLevel) { this.Connection.Open(); - this.transaction = this.Connection.BeginTransaction(isolationLevel); + this.Transaction = (EntityTransaction)this.Connection.BeginTransaction(isolationLevel); } /// <summary> + /// Gets the transaction for this data context. + /// </summary> + public EntityTransaction Transaction { get; private set; } + + /// <summary> /// Releases the resources used by the object context. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { try { this.SaveChanges(); - this.transaction.Commit(); + this.Transaction.Commit(); } finally { this.Connection.Close(); } diff --git a/projecttemplates/RelyingPartyLogic/RelyingPartyApplicationDbStore.cs b/projecttemplates/RelyingPartyLogic/RelyingPartyApplicationDbStore.cs index 9a2f8bb..e13633a 100644 --- a/projecttemplates/RelyingPartyLogic/RelyingPartyApplicationDbStore.cs +++ b/projecttemplates/RelyingPartyLogic/RelyingPartyApplicationDbStore.cs @@ -134,7 +134,7 @@ namespace RelyingPartyLogic { /// </remarks> public void ClearExpiredAssociations() { using (var dataContext = new TransactedDatabaseEntities(IsolationLevel.ReadCommitted)) { - dataContext.ClearExpiredAssociations(); + dataContext.ClearExpiredAssociations(dataContext.Transaction); } } diff --git a/projecttemplates/RelyingPartyLogic/Utilities.cs b/projecttemplates/RelyingPartyLogic/Utilities.cs index bbcfc68..6552596 100644 --- a/projecttemplates/RelyingPartyLogic/Utilities.cs +++ b/projecttemplates/RelyingPartyLogic/Utilities.cs @@ -96,21 +96,38 @@ GO } } + public static int ExecuteCommand(this ObjectContext objectContext, string command) { + // Try to automatically add the appropriate transaction if one is known. + EntityTransaction transaction = null; + if (Database.IsDataContextInitialized && Database.DataContext == objectContext) { + transaction = Database.DataContextTransaction; + } + return ExecuteCommand(objectContext, transaction, command); + } + /// <summary> /// Executes a SQL command against the SQL connection. /// </summary> /// <param name="objectContext">The object context.</param> + /// <param name="transaction">The transaction to use, if any.</param> /// <param name="command">The command to execute.</param> /// <returns>The result of executing the command.</returns> - public static int ExecuteCommand(this ObjectContext objectContext, string command) { - DbConnection connection = ((EntityConnection)objectContext.Connection).StoreConnection; + public static int ExecuteCommand(this ObjectContext objectContext, EntityTransaction transaction, string command) { + if (objectContext == null) { + throw new ArgumentNullException("objectContext"); + } + if (String.IsNullOrEmpty(command)) { + throw new ArgumentNullException("command"); + } + + DbConnection connection = (EntityConnection)objectContext.Connection; bool opening = (connection.State == ConnectionState.Closed); if (opening) { connection.Open(); } DbCommand cmd = connection.CreateCommand(); - cmd.Transaction = (DbTransaction)Database.DataContextTransaction; + cmd.Transaction = transaction; cmd.CommandText = command; cmd.CommandType = CommandType.StoredProcedure; try { |