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);
            }
        }
Exemplo n.º 2
0
 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);
        }
Exemplo n.º 5
0
        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;
        }
Exemplo n.º 6
0
 /// <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);
 }
Exemplo n.º 7
0
 public void SaveChanges(ConsistencyLevel consistencyLevel, SaveChangesMode mode = SaveChangesMode.Batch, TableType tableType = TableType.All)
 {
     saveChanges(consistencyLevel, mode, tableType);
 }
Exemplo n.º 8
0
        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);
            }
        }