static void SaveChanges_Internal(DbContext dbContext, SaveChangesMode mode, ref int counter) { var redoSaveChanges = false; if (counter >= MaxRetryCounter) { return; } try { dbContext.SaveChanges(); } catch (DbUpdateConcurrencyException cex) { if (mode == SaveChangesMode.All || mode == SaveChangesMode.IgnoreEntityDeleted) { foreach (var entiy in cex.Entries) { entiy.State = EntityState.Detached; } redoSaveChanges = true; } if (!redoSaveChanges) { throw cex; } } catch (DbUpdateException dex) { var oex = dex.InnerException?.InnerException as SqlException; if (oex?.Number == 2627) { if (mode == SaveChangesMode.All || mode == SaveChangesMode.IgnoreEntityDublicateKey) { foreach (var entry in dex.Entries) { entry.State = EntityState.Detached; } redoSaveChanges = true; } } if (!redoSaveChanges) { throw dex; } } if (redoSaveChanges) { counter++; SaveChanges_Internal(dbContext, mode, ref counter); } }
public int SaveChanges(SaveChangesMode options) { // prevent Enumeration duplication if (options == SaveChangesMode.WithoutEnumeration) { var enumObjects = ChangeTracker.Entries <Enumeration>().Where(x => x.State == EntityState.Added); foreach (var item in enumObjects) { item.State = EntityState.Unchanged; } } return(base.SaveChanges()); }
public static DataServiceResponse SaveChanges(DataServiceContext context, SaveChangesOptions options, SaveChangesMode saveMode) { IList <EntityDescriptor> entites = (from e in context.Entities where e.State != EntityStates.Unchanged select e).ToArray(); IList <LinkDescriptor> links = (from e in context.Links where e.State != EntityStates.Unchanged select e).ToArray(); IList <StreamDescriptor> streams = context.Entities.SelectMany(e => e.StreamDescriptors).Where(s => s.State != EntityStates.Unchanged).ToArray(); IList <EntityDescriptor> deletedEntities = (from e in entites where e.State == EntityStates.Deleted select e).ToArray(); IList <LinkDescriptor> deletedLinks = (from e in links where e.State == EntityStates.Deleted select e).ToArray(); DataServiceResponse response = null; switch (saveMode) { case SaveChangesMode.Synchronous: response = context.SaveChanges(options); break; case SaveChangesMode.AsyncWaitOnAsyncWaitHandle: { IAsyncResult async = context.BeginSaveChanges(options, null, null); if (!async.CompletedSynchronously) { Assert.IsTrue(async.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "BeginSaveChanges {0} timeout", options); } Assert.IsTrue(async.IsCompleted); response = context.EndSaveChanges(async); break; } case SaveChangesMode.AsyncCallback: { SaveChangesCallback callback = new SaveChangesCallback(); IAsyncResult async = context.BeginSaveChanges(options, callback.CallbackMethod, new object[] { options, context }); Assert.IsTrue(callback.Finished.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "BeginSaveChanges {0} Asyncallback timeout", options); Assert.IsTrue(async.IsCompleted); if (null != callback.CallbackFailure) { Assert.IsNull(callback.CallbackResult, callback.CallbackFailure.ToString()); throw callback.CallbackFailure; } response = (DataServiceResponse)callback.CallbackResult; break; } default: Assert.Fail("shouldn't be here"); break; } int entityIndex = 0; int linkIndex = 0; int streamIndex = 0; if (options == SaveChangesOptions.BatchWithSingleChangeset) { Assert.AreEqual <int>(response.BatchStatusCode, (int)HttpStatusCode.Accepted, "Expecting 202 as the status code for batch requests"); Assert.IsTrue(response.BatchHeaders["Content-Type"].StartsWith("multipart/mixed; boundary=batchresponse_"), "expecting content type to be multipart mixed with a boundary value"); Assert.IsTrue(response.IsBatchResponse, "Expecting response to be batch response"); } else { Assert.AreEqual <int>(response.BatchStatusCode, -1, "expecting status code to be zero"); Assert.IsTrue(response.BatchHeaders.Count == 0, "expecting no header information"); Assert.IsFalse(response.IsBatchResponse, "expecting this to be non batch response"); } foreach (ChangeOperationResponse changeset in response) { EntityStates state; bool wasDeletedState; if (changeset.Descriptor is EntityDescriptor) { EntityDescriptor tor = (EntityDescriptor)changeset.Descriptor; state = tor.State; wasDeletedState = deletedEntities.Contains(tor); // for MLE, more than one request can be sent for the same entity descriptor if (entites.Count > entityIndex && Object.ReferenceEquals(entites[entityIndex].Entity, tor.Entity)) { entityIndex++; } else { Assert.IsTrue(Object.ReferenceEquals(tor.Entity, entites[entityIndex - 1].Entity), "For MLE, it must match with the previous request"); } Assert.IsNull(changeset.Error); } else if (changeset.Descriptor is LinkDescriptor) { LinkDescriptor tor = (LinkDescriptor)changeset.Descriptor; state = tor.State; wasDeletedState = deletedLinks.Contains(tor); Assert.AreSame(tor.Source, links[linkIndex].Source); Assert.AreEqual(tor.SourceProperty, links[linkIndex].SourceProperty); Assert.AreSame(tor.Target, links[linkIndex].Target); Assert.IsNull(changeset.Error); linkIndex++; } else { Assert.IsTrue(changeset.Descriptor is StreamDescriptor, "Must be stream descriptor"); if (streams.Count > streamIndex && streams.Contains(changeset.Descriptor)) { streamIndex++; } state = changeset.Descriptor.State; wasDeletedState = false; } if (changeset.Error != null) { Assert.AreNotEqual(EntityStates.Unchanged, state); } else { if (wasDeletedState) { Assert.AreEqual(EntityStates.Detached, state); } else { Assert.AreEqual(EntityStates.Unchanged, state); } } } Assert.AreEqual(entites.Count, entityIndex, "entities SaveChangesOptions.{0}", options); Assert.AreEqual(links.Count, linkIndex, "links SaveChangesOptions.{0}", options); Assert.AreEqual(streams.Count, streamIndex, "streams SaveChangesOptions.{0}", options); entites = context.Entities; links = context.Links; return(response); }
/// <summary> /// SaveChanges supporting modes to deal with concurrency /// </summary> /// <param name="dbContext">DbContext</param> /// <param name="mode">mode to specifiy concurrency behavior</param> public static void SaveChanges(this DbContext dbContext, SaveChangesMode mode) { int counter = 0; SaveChanges_Internal(dbContext, mode, ref counter); }
private void saveChanges(ConsistencyLevel consistencyLevel, SaveChangesMode mode, TableType tableType) { var newAdditionalCommands = new List <CqlCommand>(); if (mode == SaveChangesMode.OneByOne) { foreach (KeyValuePair <string, ITable> table in _tables) { if ((((tableType & TableType.Counter) == TableType.Counter) && table.Value.GetTableType() == TableType.Counter) || (((tableType & TableType.Standard) == TableType.Standard) && table.Value.GetTableType() == TableType.Standard)) { _mutationTrackers[table.Key].SaveChangesOneByOne(this, table.Key, consistencyLevel); } } foreach (CqlCommand additional in _additionalCommands) { if ((tableType & TableType.Counter) == TableType.Counter) { if (additional.GetTable().GetTableType() == TableType.Counter) { additional.Execute(); } else if (tableType == TableType.Counter) { newAdditionalCommands.Add(additional); } } else if ((tableType & TableType.Standard) == TableType.Standard) { if (additional.GetTable().GetTableType() == TableType.Standard) { additional.Execute(); } else if (tableType == TableType.Standard) { newAdditionalCommands.Add(additional); } } } } else { if (tableType.HasFlag(TableType.Counter)) { IAsyncResult ar = BeginSaveChangesBatch(TableType.Counter, consistencyLevel, null, null); if (ar != null) { EndSaveChangesBatch(ar); } } if (tableType.HasFlag(TableType.Standard)) { IAsyncResult ar = BeginSaveChangesBatch(TableType.Standard, consistencyLevel, null, null); if (ar != null) { EndSaveChangesBatch(ar); } } } _additionalCommands = newAdditionalCommands; }
/// <summary> /// With default consistency level. /// </summary> /// <param name="mode"></param> /// <param name="tableType"></param> public void SaveChanges(SaveChangesMode mode = SaveChangesMode.Batch, TableType tableType = TableType.All) { saveChanges(_managedSession.Cluster.Configuration.QueryOptions.GetConsistencyLevel(), mode, tableType); }
public void SaveChanges(ConsistencyLevel consistencyLevel, SaveChangesMode mode = SaveChangesMode.Batch, TableType tableType = TableType.All) { saveChanges(consistencyLevel, mode, tableType); }
public void SaveChanges(SaveChangesMode mode = SaveChangesMode.Batch, TableType tableType = TableType.All, ConsistencyLevel consistencyLevel = ConsistencyLevel.Default) { var newAdditionalCommands = new List <CqlCommand>(); if (mode == SaveChangesMode.OneByOne) { foreach (var table in _tables) { if ((((tableType & TableType.Counter) == TableType.Counter) && table.Value.GetTableType() == TableType.Counter) || (((tableType & TableType.Standard) == TableType.Standard) && table.Value.GetTableType() == TableType.Standard)) { _mutationTrackers[table.Key].SaveChangesOneByOne(this, table.Key, consistencyLevel); } } foreach (var additional in _additionalCommands) { if ((tableType & TableType.Counter) == TableType.Counter) { if (additional.GetTable().GetTableType() == TableType.Counter) { additional.Execute(); } else if (tableType == TableType.Counter) { newAdditionalCommands.Add(additional); } } else if ((tableType & TableType.Standard) == TableType.Standard) { if (additional.GetTable().GetTableType() == TableType.Standard) { additional.Execute(); } else if (tableType == TableType.Standard) { newAdditionalCommands.Add(additional); } } } } else { if (((tableType & TableType.Counter) == TableType.Counter)) { bool enableTracing = false; var counterBatchScript = new StringBuilder(); foreach (var table in _tables) { if (table.Value.GetTableType() == TableType.Counter) { enableTracing |= _mutationTrackers[table.Key].AppendChangesToBatch(counterBatchScript, table.Key); } } foreach (var additional in _additionalCommands) { if (additional.GetTable().GetTableType() == TableType.Counter) { enableTracing |= additional.IsTracing; counterBatchScript.AppendLine(additional.ToString() + ";"); } else if (tableType == TableType.Counter) { newAdditionalCommands.Add(additional); } } if (counterBatchScript.Length != 0) { var res = ExecuteWriteQuery("BEGIN COUNTER BATCH\r\n" + counterBatchScript.ToString() + "\r\nAPPLY BATCH", consistencyLevel, enableTracing); foreach (var table in _tables) { if (table.Value.GetTableType() == TableType.Counter) { _mutationTrackers[table.Key].BatchCompleted(res.Info.QueryTrace); } } foreach (var additional in _additionalCommands) { additional.SetQueryTrace(res.Info.QueryTrace); } } } if (((tableType & TableType.Standard) == TableType.Standard)) { bool enableTracing = false; var batchScript = new StringBuilder(); foreach (var table in _tables) { if (table.Value.GetTableType() == TableType.Standard) { enableTracing |= _mutationTrackers[table.Key].AppendChangesToBatch(batchScript, table.Key); } } foreach (var additional in _additionalCommands) { if (additional.GetTable().GetTableType() == TableType.Standard) { enableTracing |= additional.IsTracing; batchScript.AppendLine(additional.ToString() + ";"); } else if (tableType == TableType.Standard) { newAdditionalCommands.Add(additional); } } if (batchScript.Length != 0) { var res = ExecuteWriteQuery("BEGIN BATCH\r\n" + batchScript.ToString() + "\r\nAPPLY BATCH", consistencyLevel, enableTracing); foreach (var table in _tables) { if (table.Value.GetTableType() == TableType.Standard) { _mutationTrackers[table.Key].BatchCompleted(res.Info.QueryTrace); } } foreach (var additional in _additionalCommands) { additional.SetQueryTrace(res.Info.QueryTrace); } } } } _additionalCommands = newAdditionalCommands; }
static void SaveChanges_Internal(DbContext dbContext, SaveChangesMode mode, ref int counter) { var redoSaveChanges = false; if (counter >= MaxRetryCounter) { return; } try { dbContext.SaveChanges(); } catch (DbUpdateConcurrencyException cex) { if (mode == SaveChangesMode.All || mode == SaveChangesMode.IgnoreEntityDeleted) { var oex = cex.InnerException as OptimisticConcurrencyException; if (oex != null) // -> deleted in the meantime -> update not possible { foreach (var entiy in cex.Entries) { entiy.State = EntityState.Detached; } redoSaveChanges = true; } } if (!redoSaveChanges) { throw cex; } } catch (DbUpdateException dex) { var oex = dex.InnerException?.InnerException as OracleException; if (oex != null) { if (oex.Number == 1) // 1 = dublicate key error number { if (mode == SaveChangesMode.All || mode == SaveChangesMode.IgnoreEntityDublicateKey) { foreach (var entry in dex.Entries) { entry.State = EntityState.Detached; } redoSaveChanges = true; } } } if (!redoSaveChanges) { throw dex; } } if (redoSaveChanges) { counter++; SaveChanges_Internal(dbContext, mode, ref counter); } }