1

Тема: Проблема з записом бази даних sqlite.Net core - EF-TelegramBot

Всім привіт! Пишу бота на C# Net core. Використовую Entity Framework та Sqlite і виникла проблема.
В цьому коді все працює добре

       async static Task Update(ITelegramBotClient clientBot, Telegram.Bot.Types.Update update, CancellationToken token)
        {
            var message = update.Message;
            ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(new[]
{
            new KeyboardButton[] { "Button", "Button" },
            new KeyboardButton[] { "Button", "Button" },
            new KeyboardButton[] { "Button", "Button" },
            new KeyboardButton[] { "Button", "Button" }
})
            {
                ResizeKeyboard = true
            };
            if (message.Text != null)
            {
                if (message.Text=="/start")
                {
                    await using Stream stream = System.IO.File.OpenRead(@"C:\FarmBot\FarmImage.jpg");
                    await clientBot.SendPhotoAsync(message.Chat.Id, new InputOnlineFile(stream, "FarmImage.jpg"), message.Caption = "text "+ message.Chat.FirstName + "text", replyMarkup: replyKeyboardMarkup);
                    using (ApplicationContext db = new ApplicationContext())
                    {




                        UsersDTO dto = new UsersDTO();
                        dto.TelegramID = (int)message.Chat.Id;
                        dto.Balance = 0;
                        dto.Plot = 1;
                        dto.Tractor = 0;
                        dto.Grain = 50;
                        dto.Incubator = 0;
                        dto.Chickens = 0;
                        dto.Eggs = 0;
                        db.Users.Add(dto);
                        db.SaveChanges();
                        Console.WriteLine("Данi збереженi");
                        var users = db.Users.ToList();
                        foreach (UsersDTO user in users)

                            Console.WriteLine($"{user.Id}.{user.TelegramID}, {user.Balance}, {user.Plot}");


                    }

Але це мене не влаштовує тому що кожного разу коли буде виконуватися /start буде додаватися той самий TelegtemID в базу даних де він уже є.
Якщо я намагаюсь скористатись пошуком чи є цей ID в базі видає помилку

 using (ApplicationContext db = new ApplicationContext())
                    {



                        var client = db.Users.Find((int)message.Chat.Id)
                        if(client == null){
                        UsersDTO dto = new UsersDTO();
                        dto.TelegramID = (int)message.Chat.Id;
                        dto.Balance = 0;
                        dto.Plot = 1;
                        dto.Tractor = 0;
                        dto.Grain = 50;
                        dto.Incubator = 0;
                        dto.Chickens = 0;
                        dto.Eggs = 0;
                        db.Users.Add(dto);
                        db.SaveChanges();
                        Console.WriteLine("Данi збереженi");
                        var users = db.Users.ToList();
                        foreach (UsersDTO user in users)

                            Console.WriteLine($"{user.Id}.{user.TelegramID}, {user.Balance}, {user.Plot}");
                       }


                    }

В цьому коді додав просту перевірку чи є цей клієнт в базі, якщо немає додаємо. І з цією перевіркою код вже не праює

 private static Task Error(ITelegramBotClient client, Exception exception, CancellationToken token)
 {
     throw new NotImplementedException();
   
 }

ось переходить в Task Error
Подумав можливо проблема в Task зробив окремий метод для додавання клієнтів

 if (message.Text=="/start")
{AddClient(message.Chat.Id)
}
async static void AddClient(int id) {
  await using (ApplicationContext db = new ApplicationContext())
    {
       var add = db.Users.Find(id);
        Console.WriteLine(add);
        if (add == null)
        {


            UsersDTO dto = new UsersDTO();
            dto.TelegramID = id;
            dto.Balance = 0;
            dto.Plot = 1;
            dto.Tractor = 0;
            dto.Grain = 50;
            dto.Incubator = 0;
            dto.Chickens = 0;
            dto.Eggs = 0;
            db.Users.Add(dto);
            db.SaveChanges();
            Console.WriteLine("Данi збереженi");
            var users = db.Users.ToList();
            foreach (UsersDTO user in users)

                Console.WriteLine($"{user.Id}.{user.TelegramID}, {user.Balance}, {user.Plot}");


        }

    }

Після цього Помилка стається на db.SaveChanges(); помилка 5 База даних заблокована
Що я роблю не так? Як це правильно написати?Буду вдячний будь якій допомозі

2

Re: Проблема з записом бази даних sqlite.Net core - EF-TelegramBot

Стикався з помилкою "База даних заблокована". Проблема в обмеженості самого рушія SQLite. Можна звісно городити чергу, аби обійти обмеження. Може навіть щось до певного часу й буде виходити. Однак для більш зрілих рішень радять щось доросліше, наприклад MySQL.

3

Re: Проблема з записом бази даних sqlite.Net core - EF-TelegramBot

Все добре все запрацювало виявляється база даних була відкрита в застосунку DB Browser (SQLite) і не було до неї доступу. Я незнаю як вона себе поведе коли з бота буде декілька запитів одночасно?Чи вона буде опрацьовувати їх по черзі чи помилки буде видавати

4 Востаннє редагувалося frz (13.03.2024 20:53:56)

Re: Проблема з записом бази даних sqlite.Net core - EF-TelegramBot

kinachuk1990 написав:

декілька запитів одночасно

Ото якраз і є обмеження рушія SQLite - concurrency.
Є два підходи для деякого обходу обмеження:

1) WAL (Write-Ahead Logging)

#python
conn = sqlite3.connect('mydb.db')
c = conn.cursor()
c.execute('PRAGMA journal_mode=WAL')

в цей спосіб операції запису не блокуватимуть операції читання (і навпаки)

2) збирати елементи для запису і робити це більшими батчами замість багатьох малих операцій запису.

Але як не натирай воском капот, під ним з Таврії не стане Мерседес.

kinachuk1990 написав:

буде опрацьовувати їх по черзі чи помилки буде видавати

Щоб база опрацьовувала запити по черзі, це має бути повністю організовано на боці самого додатку:
1) створення черги
2) постановка кожної операції читання і запису в чергу
3) вибирання елементу з черги і виконання операції
4) обробка результату.
Інакше буде просто помилка, і то не просто помилка а потім "відпустить" - як тільки ця недо-база заблокована через спробу аплікації виконати декілька запитів одночасно, вона вже заблокована назовсім, до моменту поки буде вбито процес і розпочато роботу наново. І не факт що не знадобиться рестарт операційки. Розробник знаючи про обмеження, в крайньому випадку закриє (вб'є) всі процеси і почне спочатку. А що зробить користувач? Скаже що програма кака.

Це класний інструмент для швидкого створення прототипів, поки не обрано конкретну "дорослу" базу, наприклад MySQL чи іншу. А також непогана річ, якщо глибоко розуміти всі обмеження і глибоко знати способи їхнього обходу. Інакше кака какою.

5

Re: Проблема з записом бази даних sqlite.Net core - EF-TelegramBot

Яку базу даних порекомендуєте саме для мого проекту?Мені не принципово з якою працювати. Але сайти якось працюють і приймають одночасно багато запитів і все працює без помилок?

6

Re: Проблема з записом бази даних sqlite.Net core - EF-TelegramBot

Postgres або MySQL. Мені подобаються обидві. Частіше обираю для пет-проектів MySQL.

Яку б з цих двох не обрали, все одно буде краще ніж SQLite.