Beispiel #1
0
        /// <summary>
        /// Update item in Database Async
        /// You should update the cache yourself (so this is NOT done)
        /// </summary>
        /// <param name="updateStatusContentList">content to update</param>
        /// <returns>same item</returns>
        public async Task <List <FileIndexItem> > UpdateItemAsync(List <FileIndexItem> updateStatusContentList)
        {
            if (!updateStatusContentList.Any())
            {
                return(new List <FileIndexItem>());
            }

            async Task <List <FileIndexItem> > LocalQuery(DbContext context, List <FileIndexItem> fileIndexItems)
            {
                foreach (var item in fileIndexItems)
                {
                    item.SetLastEdited();
                    context.Attach(item).State = EntityState.Modified;
                }

                await context.SaveChangesAsync();

                foreach (var item in fileIndexItems)
                {
                    context.Attach(item).State = EntityState.Detached;
                }

                CacheUpdateItem(fileIndexItems);
                return(fileIndexItems);
            }

            try
            {
                return(await LocalQuery(_context, updateStatusContentList));
            }
            catch (ObjectDisposedException)
            {
                var context = new InjectServiceScope(_scopeFactory).Context();
                try
                {
                    return(await LocalQuery(context, updateStatusContentList));
                }
                catch (DbUpdateConcurrencyException concurrencyException)
                {
                    SolveConcurrency.SolveConcurrencyExceptionLoop(concurrencyException.Entries);
                    return(await LocalQuery(context, updateStatusContentList));
                }
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                SolveConcurrency.SolveConcurrencyExceptionLoop(concurrencyException.Entries);
                try
                {
                    return(await LocalQuery(_context, updateStatusContentList));
                }
                catch (DbUpdateConcurrencyException e)
                {
                    var items = await GetObjectsByFilePathQueryAsync(updateStatusContentList
                                                                     .Select(p => p.FilePath).ToList());

                    _logger?.LogInformation($"double error UCL:{updateStatusContentList.Count} Count: {items.Count}", e);
                    return(updateStatusContentList);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Retry when an Exception has occured
        /// </summary>
        /// <param name="updateStatusContent"></param>
        /// <param name="e">Exception</param>
        private async Task RetrySaveChangesAsync(FileIndexItem updateStatusContent, Exception e)
        {
            _logger?.LogInformation(e, "[RetrySaveChangesAsync] retry catch-ed exception ");
            _logger?.LogInformation("[RetrySaveChangesAsync] next retry ~>");

            async Task LocalRetrySaveChangesAsyncQuery()
            {
                // InvalidOperationException: A second operation started on this context before a previous operation completed.
                // https://go.microsoft.com/fwlink/?linkid=2097913
                await Task.Delay(5);

                var context = new InjectServiceScope(_scopeFactory).Context();

                context.Attach(updateStatusContent).State = EntityState.Modified;
                await context.SaveChangesAsync();

                context.Attach(updateStatusContent).State = EntityState.Detached;
                await context.DisposeAsync();
            }

            try
            {
                await LocalRetrySaveChangesAsyncQuery();
            }
            catch (MySqlException mySqlException)
            {
                _logger?.LogError(mySqlException, "[RetrySaveChangesAsync] MySqlException catch-ed and retry again");
                await LocalRetrySaveChangesAsyncQuery();
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                SolveConcurrency.SolveConcurrencyExceptionLoop(concurrencyException.Entries);
                try
                {
                    _logger?.LogInformation("[RetrySaveChangesAsync] SolveConcurrencyExceptionLoop disposed item");
                    var context = new InjectServiceScope(_scopeFactory).Context();
                    await context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException retry2Exception)
                {
                    _logger?.LogInformation(retry2Exception,
                                            "[RetrySaveChangesAsync] save failed after DbUpdateConcurrencyException");
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Update one single item in the database
        /// For the API/update endpoint
        /// </summary>
        /// <param name="updateStatusContent">content to updated</param>
        /// <returns>this item</returns>
        public FileIndexItem UpdateItem(FileIndexItem updateStatusContent)
        {
            void LocalUpdateItemQuery(ApplicationDbContext context)
            {
                //  Update te last edited time manual
                updateStatusContent.SetLastEdited();
                context.Attach(updateStatusContent).State = EntityState.Modified;
                context.SaveChanges();
                context.Attach(updateStatusContent).State = EntityState.Detached;
                CacheUpdateItem(new List <FileIndexItem> {
                    updateStatusContent
                });
            }

            try
            {
                LocalUpdateItemQuery(_context);
            }
            catch (ObjectDisposedException error)
            {
                _logger?.LogInformation(error, "[UpdateItem] catch-ed ObjectDisposedException");
                var context = new InjectServiceScope(_scopeFactory).Context();
                LocalUpdateItemQuery(context);
            }
            catch (InvalidOperationException)
            {
                var context = new InjectServiceScope(_scopeFactory).Context();
                LocalUpdateItemQuery(context);
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                SolveConcurrency.SolveConcurrencyExceptionLoop(concurrencyException.Entries);
                try
                {
                    _context.SaveChanges();
                }
                catch (DbUpdateConcurrencyException e)
                {
                    _logger?.LogError(e, "[UpdateItem] save failed after DbUpdateConcurrencyException");
                }
            }

            return(updateStatusContent);
        }
Beispiel #4
0
        /// <summary>
        /// Update one single item in the database
        /// For the API/update endpoint
        /// </summary>
        /// <param name="updateStatusContent">content to updated</param>
        /// <returns>this item</returns>
        public async Task <FileIndexItem> UpdateItemAsync(FileIndexItem updateStatusContent)
        {
            async Task LocalQuery(DbContext context, FileIndexItem fileIndexItem)
            {
                //  Update te last edited time manual
                fileIndexItem.SetLastEdited();
                context.Attach(fileIndexItem).State = EntityState.Modified;
                await context.SaveChangesAsync();

                context.Attach(fileIndexItem).State = EntityState.Detached;
                CacheUpdateItem(new List <FileIndexItem> {
                    updateStatusContent
                });
                SetGetObjectByFilePathCache(fileIndexItem.FilePath, updateStatusContent, TimeSpan.FromMinutes(1));
            }

            try
            {
                await LocalQuery(_context, updateStatusContent);
            }
            catch (ObjectDisposedException e)
            {
                await RetrySaveChangesAsync(updateStatusContent, e);
            }
            catch (InvalidOperationException e)
            {
                // System.InvalidOperationException: Can't replace active reader.
                await RetrySaveChangesAsync(updateStatusContent, e);
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                SolveConcurrency.SolveConcurrencyExceptionLoop(concurrencyException.Entries);
                try
                {
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException e)
                {
                    _logger?.LogInformation(e, "[UpdateItemAsync] save failed after DbUpdateConcurrencyException");
                }
            }

            return(updateStatusContent);
        }
Beispiel #5
0
        /// <summary>
        /// Update a list of items in the index
        /// Used for the API/update endpoint
        /// </summary>
        /// <param name="updateStatusContentList">list of items to be updated</param>
        /// <returns>the same list, and updated in the database</returns>
        public List <FileIndexItem> UpdateItem(List <FileIndexItem> updateStatusContentList)
        {
            void LocalQuery(ApplicationDbContext context)
            {
                foreach (var item in updateStatusContentList)
                {
                    item.SetLastEdited();
                    context.Attach(item).State = EntityState.Modified;
                }
                context.SaveChanges();
            }

            try
            {
                LocalQuery(_context);
            }
            catch (ObjectDisposedException)
            {
                var context = new InjectServiceScope(_scopeFactory).Context();
                LocalQuery(context);
            }
            catch (InvalidOperationException)
            {
                var context = new InjectServiceScope(_scopeFactory).Context();
                LocalQuery(context);
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                SolveConcurrency.SolveConcurrencyExceptionLoop(concurrencyException.Entries);
                try
                {
                    _context.SaveChanges();
                }
                catch (DbUpdateConcurrencyException e)
                {
                    _logger?.LogError(e, "[List<>UpdateItem] save failed after DbUpdateConcurrencyException");
                }
            }

            CacheUpdateItem(updateStatusContentList);
            return(updateStatusContentList);
        }
Beispiel #6
0
        /// <summary>
        /// Add a new item to the database
        /// </summary>
        /// <param name="fileIndexItemList"></param>
        /// <returns>items with id</returns>
        public virtual async Task <List <FileIndexItem> > AddRangeAsync(List <FileIndexItem> fileIndexItemList)
        {
            async Task LocalQuery(ApplicationDbContext context)
            {
                await context.FileIndex.AddRangeAsync(fileIndexItemList);

                await context.SaveChangesAsync();
            }

            try
            {
                await LocalQuery(_context);
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                SolveConcurrency.SolveConcurrencyExceptionLoop(concurrencyException.Entries);
                try
                {
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException e)
                {
                    _logger?.LogError(e, "[AddRangeAsync] save failed after DbUpdateConcurrencyException");
                }
            }
            catch (ObjectDisposedException)
            {
                await LocalQuery(new InjectServiceScope(_scopeFactory).Context());
            }

            foreach (var fileIndexItem in fileIndexItemList)
            {
                AddCacheItem(fileIndexItem);
            }

            return(fileIndexItemList);
        }