Browse Source

Bug fix, refactore code

Tigran 3 years ago
parent
commit
cae615d2b7

+ 19 - 24
CardCollector/DataBase/BotDatabase.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
@@ -20,17 +19,13 @@ namespace CardCollector.DataBase
         protected DateTime _lastSave = DateTime.Now;
         
         /* Объект базы данных */
-        private static List<BotDatabase> _instances = new();
-        
-        /* Предоставляет доступ к объекту */
-        public static BotDatabase Instance
+        private static Dictionary<Type, BotDatabase> ClassInstances = new();
+
+        public static BotDatabase GetClassInstance(Type t)
         {
-            get
-            {
-                var instance = new BotDatabase();
-                _instances.Add(instance);
-                return instance;
-            }
+            if (!ClassInstances.ContainsKey(t))
+                ClassInstances.Add(t, new BotDatabase());
+            return ClassInstances[t];
         }
 
         /* Таблицы базы данных, представленные Entity объектами */
@@ -63,16 +58,8 @@ namespace CardCollector.DataBase
 
         public static async Task SaveData()
         {
-            foreach (var instance in _instances.ToList())
-            {
+            foreach (var instance in ClassInstances.Values)
                 await instance.SaveChangesAsync();
-                var activityInterval = instance._lastSave - DateTime.Now;
-                if (activityInterval.TotalMinutes > 120)
-                {
-                    _instances.Remove(instance);
-                    await instance.DisposeAsync();
-                }
-            }
         }
 
         public override void Dispose()
@@ -94,11 +81,19 @@ namespace CardCollector.DataBase
             return count;
         }
 
-        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
+        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
         {
-            var count = await base.SaveChangesAsync(cancellationToken);
-            if (count > 0) _lastSave = DateTime.Now;
-            return count;
+            try
+            {
+                var count = await base.SaveChangesAsync(cancellationToken);
+                if (count > 0) _lastSave = DateTime.Now;
+                return count;
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await SaveChangesAsync(cancellationToken);
+            }
         }
     }
 }

+ 93 - 27
CardCollector/DataBase/EntityDao/AuctionDao.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;
+using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using Microsoft.EntityFrameworkCore;
@@ -10,63 +11,128 @@ namespace CardCollector.DataBase.EntityDao
 {
     public static class AuctionDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<AuctionEntity> Table;
+
+        static AuctionDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(AuctionDao));
+            Table = Instance.Auction;
+        }
+        
         public static async Task<List<AuctionEntity>> GetProducts(string stickerId)
         {
-            var Table = BotDatabase.Instance.Auction;
-            return await Table.Where(e => e.StickerId == stickerId).ToListAsync();
+            try
+            {
+                return await Table.Where(e => e.StickerId == stickerId).ToListAsync();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetProducts(stickerId);
+            }
         }
 
         public static async Task<int> GetTotalQuantity(string stickerId)
         {
-            /* Добавил метод, который считает общее количество данных стикеров на аукционе */
-            var list = await GetProducts(stickerId);
-            return list.Sum(e => e.Count);
+            try
+            {
+                var list = await GetProducts(stickerId);
+                return list.Sum(e => e.Count);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetTotalQuantity(stickerId);
+            }
         }
 
         public static async Task<IEnumerable<StickerEntity>> GetStickers(string filter)
         {
-            var Table = BotDatabase.Instance.Auction;
-            var entityList = (await Table.ToListAsync())
-                .Select(async e => await StickerDao.GetById(e.StickerId));
-            var stickersList = await Task.WhenAll(entityList);
-            return stickersList
-                .Where(item => item.Contains(filter))
-                .GroupBy(item => item.Id)
-                .Select(item => item.First());
+            try
+            {
+                var entityList = (await Table.ToListAsync())
+                    .Select(async e => await StickerDao.GetById(e.StickerId));
+                var stickersList = await Task.WhenAll(entityList);
+                return stickersList
+                    .Where(item => item.Contains(filter))
+                    .GroupBy(item => item.Id)
+                    .Select(item => item.First());
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetStickers(filter);
+            }
         }
         //добавляем объект в аукцион
         public static async void AddNew(AuctionEntity product)
         {
-            var Table = BotDatabase.Instance.Auction;
-            await Table.AddAsync(product);
-            await BotDatabase.SaveData();
+            try
+            {
+                await Table.AddAsync(product);
+                await BotDatabase.SaveData();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                AddNew(product);
+            }
         }
         //удаляем проданный объект
         public static async Task DeleteRow(int productId)
         {
-            var Table = BotDatabase.Instance.Auction;
-            if (await Table.FirstOrDefaultAsync(c => c.Id == productId) is not { } item) return;
-            Table.Attach(item);
-            Table.Remove(item);
-            await BotDatabase.SaveData();
+            try
+            {
+                if (await Table.FirstOrDefaultAsync(c => c.Id == productId) is not { } item) return;
+                Table.Attach(item);
+                Table.Remove(item);
+                await BotDatabase.SaveData();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                await DeleteRow(productId);
+            }
         }
 
         public static async Task<bool> HaveAny(string stickerId, Expression<Func<AuctionEntity, bool>> source)
         {
-            var Table = BotDatabase.Instance.Auction;
-            return await Table.Where(i => i.StickerId == stickerId).AnyAsync(source);
+            try
+            {
+                return await Table.Where(i => i.StickerId == stickerId).AnyAsync(source);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await HaveAny(stickerId, source);
+            }
         }
 
         public static async Task<int> GetCount(int productId)
         {
-            var Table = BotDatabase.Instance.Auction;
-            return (await Table.FirstAsync(item => item.Id == productId)).Count;
+            try
+            {
+                return (await Table.FirstAsync(item => item.Id == productId)).Count;
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetCount(productId);
+            }
         }
 
         public static async Task<AuctionEntity> GetProduct(int productId)
         {
-            var Table = BotDatabase.Instance.Auction;
-            return await Table.FirstAsync(item => item.Id == productId);
+            try
+            {
+                return await Table.FirstAsync(item => item.Id == productId);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetProduct(productId);
+            }
         }
     }
 }

+ 35 - 9
CardCollector/DataBase/EntityDao/CashDao.cs

@@ -1,27 +1,53 @@
-using System.Threading.Tasks;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
+using Microsoft.EntityFrameworkCore;
 
 namespace CardCollector.DataBase.EntityDao
 {
     /* Класс, позволяющий получить доступ к объектам таблицы Cash*/
     public static class CashDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<CashEntity> Table;
+
+        static CashDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(CashDao));
+            Table = Instance.Cash;
+        }
+        
         /* Получение объекта по Id */
         public static async Task<CashEntity> GetById(long userId)
         {
-            var Table = BotDatabase.Instance.Cash;
-            var user = await Table.FindAsync(userId);
-            return user ?? await AddNew(userId);
+            try
+            {
+                var user = await Table.FindAsync(userId);
+                return user ?? await AddNew(userId);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetById(userId);
+            }
         }
 
         /* Добавление нового объекта в систему */
         private static async Task<CashEntity> AddNew(long userId)
         {
-            var Table = BotDatabase.Instance.Cash;
-            var cash = new CashEntity { UserId = userId };
-            var result = await Table.AddAsync(cash);
-            await BotDatabase.SaveData();
-            return result.Entity;
+            try
+            {
+                var cash = new CashEntity {UserId = userId};
+                var result = await Table.AddAsync(cash);
+                await BotDatabase.SaveData();
+                return result.Entity;
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await AddNew(userId);
+            }
         }
     }
 }

+ 59 - 20
CardCollector/DataBase/EntityDao/DailyTaskDao.cs

@@ -1,5 +1,7 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DailyTasks;
 using CardCollector.DataBase.Entity;
@@ -9,40 +11,77 @@ namespace CardCollector.DataBase.EntityDao
 {
     public static class DailyTaskDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<DailyTaskEntity> Table;
+
+        static DailyTaskDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(DailyTaskDao));
+            Table = Instance.DailyTasks;
+        }
+        
         public static async Task<List<DailyTaskEntity>> GetAll()
         {
-            var Table = BotDatabase.Instance.DailyTasks;
-            return await Table.ToListAsync();
+            try
+            {
+                return await Table.ToListAsync();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetAll();
+            }
         }
 
         /* Добавляет новое отношение в таблицу */
         public static async Task<DailyTaskEntity> AddNew(long userId, int taskId)
         {
-            var Table = BotDatabase.Instance.DailyTasks;
-            if (await Table.FirstOrDefaultAsync(item => item.UserId == userId && item.TaskId == taskId) is { } obj)
-                return obj;
-            var newTask = new DailyTaskEntity()
-            {
-                TaskId = taskId,
-                UserId = userId,
-                Progress = DailyTask.List[(DailyTaskKeys)taskId].Goal
-            };
-            var result = await Table.AddAsync(newTask);
-            await BotDatabase.SaveData();
-            return result.Entity;
+            try
+            {
+                if (await Table.FirstOrDefaultAsync(item => item.UserId == userId && item.TaskId == taskId) is { } obj)
+                    return obj;
+                var newTask = new DailyTaskEntity()
+                {
+                    TaskId = taskId,
+                    UserId = userId,
+                    Progress = DailyTask.List[(DailyTaskKeys) taskId].Goal
+                };
+                var result = await Table.AddAsync(newTask);
+                await BotDatabase.SaveData();
+                return result.Entity;
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await AddNew(userId, taskId);
+            }
         }
 
         public static async Task<DailyTaskEntity> GetTaskInfo(long userId, int taskId)
         {
-            var Table = BotDatabase.Instance.DailyTasks;
-            return await Table.FirstOrDefaultAsync(item => item.UserId == userId && item.TaskId == taskId)
-                   ?? await AddNew(userId, taskId);
+            try
+            {
+                return await Table.FirstOrDefaultAsync(item => item.UserId == userId && item.TaskId == taskId)
+                       ?? await AddNew(userId, taskId);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetTaskInfo(userId, taskId);
+            }
         }
 
         public static async Task<Dictionary<int, DailyTaskEntity>> GetUserTasks(long userId)
         {
-            var Table = BotDatabase.Instance.DailyTasks;
-            return await Table.Where(item => item.UserId == userId).ToDictionaryAsync(p => p.TaskId, p => p);
+            try
+            {
+                return await Table.Where(item => item.UserId == userId).ToDictionaryAsync(p => p.TaskId, p => p);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetUserTasks(userId);
+            }
         }
     }
 }

+ 19 - 2
CardCollector/DataBase/EntityDao/LevelDao.cs

@@ -1,4 +1,6 @@
 #nullable enable
+using System;
+using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using Microsoft.EntityFrameworkCore;
@@ -7,12 +9,27 @@ namespace CardCollector.DataBase.EntityDao
 {
     public class LevelDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<Level> Table;
+
+        static LevelDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(LevelDao));
+            Table = Instance.Levels;
+        }
         
         /* Получение объекта по Id */
         public static async Task<Level?> GetLevel(int level)
         {
-            var Table = BotDatabase.Instance.Levels;
-            return await Table.FirstOrDefaultAsync(item => item.LevelValue == level);
+            try
+            {
+                return await Table.FirstOrDefaultAsync(item => item.LevelValue == level);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetLevel(level);
+            }
         }
 
         /* Добавление нового объекта в систему */

+ 46 - 13
CardCollector/DataBase/EntityDao/PacksDao.cs

@@ -2,6 +2,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using Microsoft.EntityFrameworkCore;
@@ -10,30 +11,62 @@ namespace CardCollector.DataBase.EntityDao
 {
     public static class PacksDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<PackEntity> Table;
+
+        static PacksDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(PacksDao));
+            Table = Instance.Packs;
+        }
+    
         public static async Task<PackEntity> GetById(int id)
         {
-            var Table = BotDatabase.Instance.Packs;
-            return await Table.FirstOrDefaultAsync(item => item.Id == id);
+            try
+            {
+                return await Table.FirstOrDefaultAsync(item => item.Id == id);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetById(id);
+            }
         }
         
         public static async Task<PackEntity> AddNew(string author, string description = "")
         {
-            var Table = BotDatabase.Instance.Packs;
-            var result = await Table.AddAsync(new PackEntity
+            try
             {
-                Author = author,
-                Description = description
-            });
-            await BotDatabase.SaveData();
-            return result.Entity;
+                var result = await Table.AddAsync(new PackEntity
+                {
+                    Author = author,
+                    Description = description
+                });
+                await BotDatabase.SaveData();
+                return result.Entity;
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await AddNew(author, description);
+            }
+            
         }
 
         public static async Task<List<PackEntity>> GetAll()
         {
-            var Table = BotDatabase.Instance.Packs;
-            var list = await Table.Where(item => item.Id != 1).ToListAsync();
-            list.Sort(new AuthorComparer());
-            return list;
+            try
+            {
+                var list = await Table.Where(item => item.Id != 1).ToListAsync();
+                list.Sort(new AuthorComparer());
+                return list;
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetAll();
+            }
+            
         }
 
         private class AuthorComparer : IComparer<PackEntity>

+ 22 - 6
CardCollector/DataBase/EntityDao/SessionTokenDao.cs

@@ -1,18 +1,34 @@
-using System.Threading.Tasks;
+using System;
+using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
+using Microsoft.EntityFrameworkCore;
 
 namespace CardCollector.DataBase.EntityDao
 {
     public static class SessionTokenDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<SessionToken> Table;
+
+        static SessionTokenDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(SessionTokenDao));
+            Table = Instance.SessionTokens;
+        }
 
         public static async Task AddNew(long userId, string token)
         {
-            var Table = BotDatabase.Instance.SessionTokens;
-            var result = await Table.AddAsync(new SessionToken {UserId = userId, Token = token});
-            await BotDatabase.SaveData();
-            Table.Attach(result.Entity);
-            BotDatabase.Instance.ChangeTracker.Clear();
+            try
+            {
+                var result = await Table.AddAsync(new SessionToken {UserId = userId, Token = token});
+                await BotDatabase.SaveData();
+                Table.Attach(result.Entity);
+                Instance.ChangeTracker.Clear();
+            }
+            catch (InvalidOperationException)
+            {
+                Logs.LogOut("Cant creat token");
+            }
         }
     }
 }

+ 42 - 10
CardCollector/DataBase/EntityDao/SettingsDao.cs

@@ -1,4 +1,6 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using Microsoft.EntityFrameworkCore;
@@ -7,25 +9,55 @@ namespace CardCollector.DataBase.EntityDao
 {
     public static class SettingsDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<UserSettings> Table;
+
+        static SettingsDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(SettingsDao));
+            Table = Instance.Settings;
+        }
+        
         public static async Task<UserSettings> GetById(long userId)
         {
-            var Table = BotDatabase.Instance.Settings;
-            return await Table.FirstOrDefaultAsync(item => item.UserId == userId) ?? await AddNew(userId);
+            try
+            {
+                return await Table.FirstOrDefaultAsync(item => item.UserId == userId) ?? await AddNew(userId);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetById(userId);
+            }
         }
         
         public static async Task<UserSettings> AddNew(long userId)
         {
-            var Table = BotDatabase.Instance.Settings;
-            var entry = new UserSettings {UserId = userId};
-            entry.InitProperties();
-            var result = await Table.AddAsync(entry);
-            return result.Entity;
+            try
+            {
+                var entry = new UserSettings {UserId = userId};
+                entry.InitProperties();
+                var result = await Table.AddAsync(entry);
+                return result.Entity;
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await AddNew(userId);
+            }
         }
 
         public static async Task<Dictionary<long, UserSettings>> GetAll()
         {
-            var Table = BotDatabase.Instance.Settings;
-            return await Table.ToDictionaryAsync(item => item.UserId, item => item);
+            try
+            {
+                return await Table.ToDictionaryAsync(item => item.UserId, item => item);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetAll();
+            }
         }
     }
 }

+ 39 - 7
CardCollector/DataBase/EntityDao/ShopDao.cs

@@ -1,5 +1,7 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using Microsoft.EntityFrameworkCore;
@@ -8,22 +10,52 @@ namespace CardCollector.DataBase.EntityDao
 {
     public static class ShopDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<ShopEntity> Table;
+
+        static ShopDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(ShopDao));
+            Table = Instance.Shop;
+        }
+        
         public static async Task<IEnumerable<ShopEntity>> GetShopPositions()
         {
-            var Table = BotDatabase.Instance.Shop;
-            return (await Table.ToListAsync()).Where(e => !e.IsSpecial);
+            try
+            {
+                return (await Table.ToListAsync()).Where(e => !e.IsSpecial);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetShopPositions();
+            }
         }
         
         public static async Task<IEnumerable<ShopEntity>> GetSpecialPositions()
         {
-            var Table = BotDatabase.Instance.Shop;
-            return (await Table.ToListAsync()).Where(e => e.IsSpecial && !e.Expired);
+            try
+            {
+                return (await Table.ToListAsync()).Where(e => e.IsSpecial && !e.Expired);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetSpecialPositions();
+            }
         }
 
         public static async Task<ShopEntity> GetById(int positionId)
         {
-            var Table = BotDatabase.Instance.Shop;
-            return await Table.FirstAsync(e => e.Id == positionId);
+            try
+            {
+                return await Table.FirstAsync(e => e.Id == positionId);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetById(positionId);
+            }
         }
     }
 }

+ 34 - 9
CardCollector/DataBase/EntityDao/SpecialOfferUsersDao.cs

@@ -1,4 +1,6 @@
-using System.Threading.Tasks;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using Microsoft.EntityFrameworkCore;
 
@@ -6,21 +8,44 @@ namespace CardCollector.DataBase.EntityDao
 {
     public class SpecialOfferUsersDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<SpecialOfferUsers> Table;
+
+        static SpecialOfferUsersDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(SpecialOfferUsersDao));
+            Table = Instance.SpecialOfferUsers;
+        }
+        
         public static async Task<bool> NowUsed(long userId, int offerId)
         {
-            var Table = BotDatabase.Instance.SpecialOfferUsers;
-            return await Table.AnyAsync(e => e.UserId == userId && e.OfferId == offerId);
+            try
+            {
+                return await Table.AnyAsync(e => e.UserId == userId && e.OfferId == offerId);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await NowUsed(userId, offerId);
+            }
         }
 
         public static async Task AddNew(long userId, int offerId)
         {
-            var Table = BotDatabase.Instance.SpecialOfferUsers;
-            await Table.AddAsync(new SpecialOfferUsers
+            try
+            {
+                await Table.AddAsync(new SpecialOfferUsers
+                {
+                    UserId = userId,
+                    OfferId = offerId
+                });
+                await BotDatabase.SaveData();
+            }
+            catch (InvalidOperationException)
             {
-                UserId = userId,
-                OfferId = offerId
-            });
-            await BotDatabase.SaveData();
+                Thread.Sleep(Utilities.rnd.Next(30));
+                await AddNew(userId, offerId);
+            }
         }
     }
 }

+ 80 - 21
CardCollector/DataBase/EntityDao/StickerDao.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;
+using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using Microsoft.EntityFrameworkCore;
@@ -11,54 +12,112 @@ namespace CardCollector.DataBase.EntityDao
     /* Класс, предоставляющий доступ к объектам таблицы Stickers*/
     public static class StickerDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<StickerEntity> Table;
+
+        static StickerDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(StickerDao));
+            Table = Instance.Stickers;
+        }
+        
         /* Получение информации о стикере по его хешу, возвращает Null, если стикера не существует */
         public static async Task<StickerEntity> GetByHash(string hash)
         {
-            var Table = BotDatabase.Instance.Stickers;
-            return await Table.FirstOrDefaultAsync(item => item.Md5Hash == hash);
+            try
+            {
+                return await Table.FirstOrDefaultAsync(item => item.Md5Hash == hash);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetByHash(hash);
+            }
         }
 
         public static async Task<List<string>> GetAuthorsList()
         {
-            var Table = BotDatabase.Instance.Stickers;
-            var list = await Table.Select(item => item.Author).Distinct().ToListAsync();
-            list.Sort();
-            return list;
+            try
+            {
+                var list = await Table.Select(item => item.Author).Distinct().ToListAsync();
+                list.Sort();
+                return list;
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetAuthorsList();
+            }
         }
 
         public static async Task<List<StickerEntity>> GetAll(string filter = "")
         {
-            var Table = BotDatabase.Instance.Stickers;
-            return await Table.Where(item => item.Contains(filter)).ToListAsync();
+            try
+            {
+                return await Table.Where(item => item.Contains(filter)).ToListAsync();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetAll(filter);
+            }
         }
 
         public static async Task AddNew(StickerEntity sticker)
         {
-            var Table = BotDatabase.Instance.Stickers;
-            await Table.AddAsync(sticker);
-            await BotDatabase.SaveData();
+            try
+            {
+                await Table.AddAsync(sticker);
+                await BotDatabase.SaveData();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                await AddNew(sticker);
+            }
         }
 
         public static async Task AddRange(IEnumerable<StickerEntity> stickers, int packId)
         {
-            var Table = BotDatabase.Instance.Stickers;
-            await Table.AddRangeAsync(stickers.Select(item => {
-                item.PackId = packId;
-                return item;
-            }));
-            await BotDatabase.SaveData();
+            try
+            {
+                await Table.AddRangeAsync(stickers.Select(item => {
+                    item.PackId = packId;
+                    return item;
+                }));
+                await BotDatabase.SaveData();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                await AddRange(stickers, packId);
+            }
         }
 
         public static async Task<List<StickerEntity>> GetListWhere(Expression<Func<StickerEntity, bool>> func)
         {
-            var Table = BotDatabase.Instance.Stickers;
-            return await Table.Where(func).ToListAsync();
+            try
+            {
+                return await Table.Where(func).ToListAsync();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetListWhere(func);
+            }
         }
 
         public static async Task<StickerEntity> GetById(string id)
         {
-            var Table = BotDatabase.Instance.Stickers;
-            return await Table.FirstOrDefaultAsync(sticker => sticker.Id == id);
+            try
+            {
+                return await Table.FirstOrDefaultAsync(sticker => sticker.Id == id);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetById(id);
+            }
         }
     }
 }

+ 76 - 35
CardCollector/DataBase/EntityDao/UserDao.cs

@@ -2,12 +2,12 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;
+using System.Threading;
 using System.Threading.Tasks;
 using System.Timers;
 using CardCollector.Controllers;
 using CardCollector.DataBase.Entity;
 using CardCollector.Resources;
-using CardCollector.Session.Modules;
 using Microsoft.EntityFrameworkCore;
 using Telegram.Bot.Types;
 
@@ -16,6 +16,15 @@ namespace CardCollector.DataBase.EntityDao
     /* Класс, предоставляющий доступ к объектам пользователей таблицы Users */
     public static class UserDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<UserEntity> Table;
+
+        static UserDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(UserDao));
+            Table = Instance.Users;
+        }
+
         /* Активные пользователи в системе */
         private static readonly Dictionary<long, UserEntity> ActiveUsers = new();
 
@@ -23,25 +32,24 @@ namespace CardCollector.DataBase.EntityDao
         public static async Task<UserEntity> GetUser(User user)
         {
             UserEntity result;
-            try
-            {
-                /* Пытаемся получить пользователя из списка активных */
+            if (ActiveUsers.ContainsKey(user.Id))
                 result = ActiveUsers[user.Id];
-            }
-            catch
+            else
             {
-                var Table = BotDatabase.Instance.Users;
-                /* Ищем пользователя в базе данных или добавляем нового, если не найден*/
-                result = await Table.FindAsync(user.Id) ?? await AddNew(user);
-                
+                try
+                {
+                    result = await Table.FirstOrDefaultAsync(item => item.Id == user.Id) ?? await AddNew(user);
+                }
+                catch (InvalidOperationException)
+                {
+                    Thread.Sleep(Utilities.rnd.Next(30));
+                    return await GetUser(user);
+                }
                 /* Собираем объект пользователя */
                 result.Cash = await CashDao.GetById(user.Id);
                 result.Stickers = await UserStickerRelationDao.GetListById(user.Id);
                 result.Settings = await SettingsDao.GetById(user.Id);
                 result.CurrentLevel = await UserLevelDao.GetById(user.Id);
-                result.Session.InitNewModule<FiltersModule>();
-                result.Session.InitNewModule<DefaultModule>();
-                
                 /* Добавляем пользователя в список активных, чтобы не обращаться к бд лишний раз */
                 ActiveUsers.Add(user.Id, result);
             }
@@ -52,34 +60,52 @@ namespace CardCollector.DataBase.EntityDao
 
         public static async Task<UserEntity> GetById(long userId)
         {
-            var Table = BotDatabase.Instance.Users;
-            var user = await Table.FirstAsync(item => item.Id == userId);
-            user.Cash = await CashDao.GetById(user.Id);
-            //user.Stickers = await UserStickerRelationDao.GetListById(user.Id);
-            return user;
+            try
+            {
+                return await Table.FirstOrDefaultAsync(item => item.Id == userId);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetById(userId);
+            }
         }
 
         /* Получение пользователя по представлению user из Базы данных */
         public static async Task<List<UserEntity>> GetUsersList(string filter)
         {
-            var Table = BotDatabase.Instance.Users;
-            return await Table.Where(user => user.Username.Contains(filter)).ToListAsync();
+            try
+            {
+                return await Table.Where(user => user.Username.Contains(filter)).ToListAsync();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetUsersList(filter);
+            }
         }
 
         /* Добавление новго пользователя в систему */
         private static async Task<UserEntity> AddNew(User user)
         {
-            var Table = BotDatabase.Instance.Users;
-            var userEntity = new UserEntity
+            try
+            {
+                var userEntity = new UserEntity
+                {
+                    Id = user.Id,
+                    ChatId = user.Id,
+                    Username = user.Username != "" ? user.Username : "user"+user.Id,
+                    IsBlocked = false
+                };
+                var result = await Table.AddAsync(userEntity);
+                await BotDatabase.SaveData();
+                return result.Entity;
+            }
+            catch (InvalidOperationException)
             {
-                Id = user.Id,
-                ChatId = user.Id,
-                Username = user.Username != "" ? user.Username : "user"+user.Id,
-                IsBlocked = false
-            };
-            var result = await Table.AddAsync(userEntity);
-            await BotDatabase.SaveData();
-            return result.Entity;
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await AddNew(user);
+            }
         }
 
         public static async void ClearMemory(object sender, ElapsedEventArgs e)
@@ -102,16 +128,31 @@ namespace CardCollector.DataBase.EntityDao
             }
         }
 
-        public static Task<List<UserEntity>> GetAllWhere(Expression<Func<UserEntity, bool>> callback)
+        public static async Task<List<UserEntity>> GetAllWhere(Expression<Func<UserEntity, bool>> callback)
         {
-            var Table = BotDatabase.Instance.Users;
-            return Table.Where(callback).ToListAsync();
+            try
+            {
+                return await Table.Where(callback).ToListAsync();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetAllWhere(callback);
+            }
         }
 
         public static async Task<IEnumerable<UserEntity>> GetAll()
         {
-            var Table = BotDatabase.Instance.Users;
-            return await Table.ToListAsync();
+            
+            try
+            {
+                return await Table.ToListAsync();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetAll();
+            }
         }
     }
 }

+ 44 - 12
CardCollector/DataBase/EntityDao/UserLevelDao.cs

@@ -1,5 +1,7 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using Microsoft.EntityFrameworkCore;
@@ -8,28 +10,58 @@ namespace CardCollector.DataBase.EntityDao
 {
     public class UserLevelDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<UserLevel> Table;
+
+        static UserLevelDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(UserLevelDao));
+            Table = Instance.UserLevel;
+        }
+        
         /* Получение объекта по Id */
         public static async Task<UserLevel> GetById(long userId)
         {
-            var Table = BotDatabase.Instance.UserLevel;
-            var user = await Table.FirstOrDefaultAsync(item => item.UserId == userId);
-            return user ?? await AddNew(userId);
+            try
+            {
+                var user = await Table.FirstOrDefaultAsync(item => item.UserId == userId);
+                return user ?? await AddNew(userId);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetById(userId);
+            }
         }
 
         /* Добавление нового объекта в систему */
         private static async Task<UserLevel> AddNew(long userId)
         {
-            var Table = BotDatabase.Instance.UserLevel;
-            var userLevel = new UserLevel { UserId = userId };
-            var result = await Table.AddAsync(userLevel);
-            await BotDatabase.SaveData();
-            return result.Entity;
+            try
+            {
+                var userLevel = new UserLevel { UserId = userId };
+                var result = await Table.AddAsync(userLevel);
+                await BotDatabase.SaveData();
+                return result.Entity;
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await AddNew(userId);
+            }
         }
 
-        public static Task<List<UserLevel>> GetTop(int top)
+        public static async Task<List<UserLevel>> GetTop(int top)
         {
-            var Table = BotDatabase.Instance.UserLevel;
-            return Table.OrderByDescending(item => item.TotalExp).Take(top).ToListAsync();
+            try
+            {
+                return await Table.OrderByDescending(item => item.TotalExp).Take(top).ToListAsync();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetTop(top);
+            }
         }
     }
 }

+ 43 - 11
CardCollector/DataBase/EntityDao/UserPacksDao.cs

@@ -1,5 +1,7 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using Microsoft.EntityFrameworkCore;
@@ -8,26 +10,56 @@ namespace CardCollector.DataBase.EntityDao
 {
     public static class UserPacksDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<UserPacks> Table;
+
+        static UserPacksDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(UserPacksDao));
+            Table = Instance.UsersPacks;
+        }
+        
         public static async Task<List<UserPacks>> GetUserPacks(long userId)
         {
-            var Table = BotDatabase.Instance.UsersPacks;
-            return await Table.Where(item => item.UserId == userId).ToListAsync();
+            try
+            {
+                return await Table.Where(item => item.UserId == userId).ToListAsync();
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetUserPacks(userId);
+            }
         }
 
         public static async Task<UserPacks> AddNew(long userId, int packId)
         {
-            var Table = BotDatabase.Instance.UsersPacks;
-            var newPack = new UserPacks() { UserId = userId, PackId = packId };
-            var result = await Table.AddAsync(newPack);
-            await BotDatabase.SaveData();
-            return result.Entity;
+            try
+            {
+                var newPack = new UserPacks() { UserId = userId, PackId = packId };
+                var result = await Table.AddAsync(newPack);
+                await BotDatabase.SaveData();
+                return result.Entity;
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await AddNew(userId, packId);
+            }
         }
 
         public static async Task<UserPacks> GetOne(long userId, int packId)
         {
-            var Table = BotDatabase.Instance.UsersPacks;
-            return await Table.FirstOrDefaultAsync(item => item.UserId == userId && item.PackId == packId)
-                   ?? await AddNew(userId, packId);
+            try
+            {
+                return await Table.FirstOrDefaultAsync(item => item.UserId == userId && item.PackId == packId)
+                       ?? await AddNew(userId, packId);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetOne(userId, packId);
+            }
         }
     }
 }

+ 43 - 19
CardCollector/DataBase/EntityDao/UserStickerRelationDao.cs

@@ -1,5 +1,7 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using Microsoft.EntityFrameworkCore;
@@ -9,35 +11,57 @@ namespace CardCollector.DataBase.EntityDao
     /* Предоставляет доступ к соотношениям таблицы user_to_sticker_relation */
     public static class UserStickerRelationDao
     {
+        public static BotDatabase Instance;
+        public static DbSet<UserStickerRelationEntity> Table;
+
+        static UserStickerRelationDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(UserStickerRelationDao));
+            Table = Instance.UserStickerRelations;
+        }
+        
         /* Возвращает словарь стикеров по Id пользователя */
         public static async Task<Dictionary<string, UserStickerRelationEntity>> GetListById(long userId)
         {
-            var Table = BotDatabase.Instance.UserStickerRelations;
-            var result = await Table.Where(i => i.UserId == userId).ToDictionaryAsync(p=> p.ShortHash, p=> p);
-            return result;
+            try
+            {
+                return await Table.Where(i => i.UserId == userId).ToDictionaryAsync(p=> p.ShortHash, p=> p);
+            }
+            catch (InvalidOperationException)
+            {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await GetListById(userId);
+            }
         }
 
         /* Добавляет новое отношение в таблицу */
         public static async Task<UserStickerRelationEntity> AddSticker(UserEntity user, StickerEntity sticker, int count = 1)
         {
-            var Table = BotDatabase.Instance.UserStickerRelations;
-            if (user.Stickers.ContainsKey(sticker.Md5Hash))
+            try
             {
-                user.Stickers[sticker.Md5Hash].Count += count;
-                return user.Stickers[sticker.Md5Hash];
+                if (user.Stickers.ContainsKey(sticker.Md5Hash))
+                {
+                    user.Stickers[sticker.Md5Hash].Count += count;
+                    return user.Stickers[sticker.Md5Hash];
+                }
+                var relation = new UserStickerRelationEntity
+                {
+                    UserId = user.Id,
+                    StickerId = sticker.Id,
+                    Count = count,
+                    ShortHash = sticker.Md5Hash
+                };
+                await sticker.ApplyEffect(user, relation);
+                var result = await Table.AddAsync(relation);
+                user.Stickers.Add(sticker.Md5Hash, result.Entity);
+                await BotDatabase.SaveData();
+                return result.Entity;
             }
-            var relation = new UserStickerRelationEntity
+            catch (InvalidOperationException)
             {
-                UserId = user.Id,
-                StickerId = sticker.Id,
-                Count = count,
-                ShortHash = sticker.Md5Hash
-            };
-            await sticker.ApplyEffect(user, relation);
-            var result = await Table.AddAsync(relation);
-            user.Stickers.Add(sticker.Md5Hash, result.Entity);
-            await BotDatabase.SaveData();
-            return result.Entity;
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await AddSticker(user, sticker, count);
+            }
         }
     }
 }

+ 1 - 1
CardCollector/Resources/Constants.cs

@@ -5,7 +5,7 @@ namespace CardCollector.Resources
     public static class Constants
     {
         /* Переключить данный флаг при сборке на сервер */
-        public const bool DEBUG = false;
+        public const bool DEBUG = true;
 
         /* Интервал сохранения изменений */
         public const double SAVING_CHANGES_INTERVAL = DEBUG ? 10 * 1000 : 5 * 60 * 1000;

+ 1 - 1
CardCollector/TimerTasks/DailyTaskAlert.cs

@@ -9,7 +9,7 @@ namespace CardCollector.TimerTasks
 {
     public class DailyTaskAlert : TimerTask
     {
-        protected override TimeSpan RunAt => Constants.DEBUG ? new TimeSpan(10, 17, 20) : new TimeSpan(10, 0, 0);
+        protected override TimeSpan RunAt => Constants.DEBUG ? new TimeSpan(12, 14, 20) : new TimeSpan(10, 0, 0);
         
         protected override async void TimerCallback(object o, ElapsedEventArgs e)
         {

+ 1 - 1
CardCollector/TimerTasks/DailyTaskReset.cs

@@ -8,7 +8,7 @@ namespace CardCollector.TimerTasks
 {
     public class DailyTaskReset : TimerTask
     {
-        protected override TimeSpan RunAt => Constants.DEBUG ? new TimeSpan(10, 17, 20) : new TimeSpan(10, 0, 0);
+        protected override TimeSpan RunAt => Constants.DEBUG ? new TimeSpan(12, 14, 20) : new TimeSpan(10, 0, 0);
 
         protected override async void TimerCallback(object o, ElapsedEventArgs e)
         {

+ 1 - 1
CardCollector/TimerTasks/ExecuteStickerEffects.cs

@@ -11,7 +11,7 @@ namespace CardCollector.TimerTasks
 {
     public class ExecuteStickerEffects : TimerTask
     {
-        protected override TimeSpan RunAt => Constants.DEBUG ? new TimeSpan(10, 17, 20) : new TimeSpan(11, 0, 0);
+        protected override TimeSpan RunAt => Constants.DEBUG ? new TimeSpan(12, 14, 20) : new TimeSpan(11, 0, 0);
         
         protected override async void TimerCallback(object o, ElapsedEventArgs e)
         {

+ 1 - 2
CardCollector/TimerTasks/PiggyBankAlert.cs

@@ -12,9 +12,8 @@ namespace CardCollector.TimerTasks
         protected override TimeSpan RunAt => Get();
         public TimeSpan Get()
         {
-            Logs.LogOut("Get PiggyBankAlert RunAt");
             return Constants.DEBUG 
-                ? new TimeSpan(10, 34, 0) 
+                ? new TimeSpan(12, 14, 20) 
                 : new TimeSpan((DateTime.Now.TimeOfDay.Hours % 4 + 1) * 4, 0, 0);
         }
         

+ 1 - 1
CardCollector/TimerTasks/ResetChatGiveExp.cs

@@ -7,7 +7,7 @@ namespace CardCollector.TimerTasks
 {
     public class ResetChatGiveExp : TimerTask
     {
-        protected override TimeSpan RunAt => Constants.DEBUG ? new TimeSpan(10, 17, 20) : new TimeSpan(10, 0, 0);
+        protected override TimeSpan RunAt => Constants.DEBUG ? new TimeSpan(12, 14, 20) : new TimeSpan(10, 0, 0);
         
         protected override void TimerCallback(object o, ElapsedEventArgs e)
         {

+ 1 - 1
CardCollector/TimerTasks/TopExpUsersAlert.cs

@@ -10,7 +10,7 @@ namespace CardCollector.TimerTasks
 {
     public class TopExpUsersAlert : TimerTask
     {
-        protected override TimeSpan RunAt => Constants.DEBUG ? new TimeSpan(10, 17, 20) : new TimeSpan(24, 0, 0);
+        protected override TimeSpan RunAt => Constants.DEBUG ? new TimeSpan(12, 14, 20) : new TimeSpan(24, 0, 0);
         
         protected override async void TimerCallback(object o, ElapsedEventArgs e)
         {