2 место Заготовка для работы с БД MySQL в кубике C#

Shining

Client
Регистрация
25.05.2018
Сообщения
35
Благодарностей
0
Баллы
6
1) посмотреть в конфиге mysql сколько вообще одновременных подключений разрешено - параметр max_connections
2) выставить в конфеге mysql достаточный wait_timeout - возможно сервер банально разрывает соединение из-за того что нет активности
3) дописать в методы getOne, getRow, getAll, query проверку на валидность соединения перед их выполнением и если не валидно - опять делать open

примерно так
C#:
if ( conn.State != ConnectionState.Open ){
    open(); 
}
Здравствуйте, вознакают ошибки при любом изменении конфига или банально не вступают в силу. Ищу другой способ увеличить таймаут соединение более 60 секунда. Скажите, есть ли смысл в строке подключения передавать такой параметр или воозможно нужен какой-то другой?

C#:
//вконце строки Сonnection Timeout=120
var connectionString = "server="+db_hostname+";user="+db_username+";database="+db_database+";port="+db_port+";password="+db_password+";pooling=False;Сonnection Timeout=120";
 

Shining

Client
Регистрация
25.05.2018
Сообщения
35
Благодарностей
0
Баллы
6
Вот в логах видно обрывается соединение на 60 секунде и не понимаю как увеличить его
73773


В проджекте такая ошибка: "Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding."
 

angelxzol

Новичок
Регистрация
12.03.2021
Сообщения
6
Благодарностей
1
Баллы
1

Dimon174

Client
Регистрация
30.12.2019
Сообщения
20
Благодарностей
11
Баллы
3
WebBot, огромнейшее вам спасибо за статью)) Благодаря ей, узнал все основные принципы в работе с mysql и отказался во всех проектах, от таблиц и списков. Также начал собирать большую часть проектов на C#, хотя в нем вообще не разбираюсь и не изучал :D А сейчас и с циклами, и с условиями проверки спокойно оперирую :-) Все благодаря вашей статье с хорошим инструкциями.
Итог: Изучал статью для работы с mysql, а начал ещё и в c# разбираться (основы по крайней мере):D
 

kolik

Client
Регистрация
11.12.2017
Сообщения
47
Благодарностей
8
Баллы
8
Всем привет, при взятии строки выходит такая ошибка: Выполнение действия CSharp OwnCode: взять аккаунт. [Строка: 31; Cтолбец: 0] Выдано исключение типа "System.Exception". Подскажите в какую сторону копать?

P.S. Разобрался.
 
Последнее редактирование:

Shining

Client
Регистрация
25.05.2018
Сообщения
35
Благодарностей
0
Баллы
6
В гугл таблицах есть функция "Вставить изображение в ячейку". Подскажите как можно сделать тоже самое в зенопостере? Возможно через HttpPost запрос?

Шаблоном пользуюсь хоть и появилась данная возможность в новой Зенке. Автору респект!
 

Вложения

New_neo

Client
Регистрация
18.03.2021
Сообщения
5
Благодарностей
1
Баллы
3
@zenno.xxx
Судя по всему не может найти класс DB который в заготовке находится в общем коде.
1. Вы используете заготовку с уже включенным в общий код классом?
2. MySql.Data.dll скопирован для вашей версии ZP из папки Progs в папку ExternalAssemblies ?
Я сделал все как написано и не работает! DB он не может найти! Подскажите - где то что такое простое, потому что не видит он DB
 

New_neo

Client
Регистрация
18.03.2021
Сообщения
5
Благодарностей
1
Баллы
3
DB db = new DB(db_host, db_user, db_pswd, db_database, db_charset);
Не работает! Добавил файл как описано! В кубике создаю экземпляр класса DB и он его не видит! В чем секрет?
 

Koqpe

Client
Регистрация
23.12.2014
Сообщения
1 100
Благодарностей
649
Баллы
113
Я сделал все как написано и не работает!
Сделал бы все как написано, все бы работало, возьми прикрепленный к первому посту шаблон с примером и подставь свои данные.
 

New_neo

Client
Регистрация
18.03.2021
Сообщения
5
Благодарностей
1
Баллы
3
Тип Время Сообщение
14:49:58 Компиляция кода проекта Ошибка при компиляции общего кода "CS0246" "The type or namespace name 'DB' could not be found (are you missing a using directive or an assembly reference?)". [Строка: 62; Cтолбец: 4]
 

Koqpe

Client
Регистрация
23.12.2014
Сообщения
1 100
Благодарностей
649
Баллы
113
Понятно, легких путей не ищешь...
 

New_neo

Client
Регистрация
18.03.2021
Сообщения
5
Благодарностей
1
Баллы
3
Нашел - спасибо, нужно было создать публичный класс DB и поехало. Спасибо!
 
  • Спасибо
Реакции: Koqpe

bigloafer

Client
Регистрация
23.07.2020
Сообщения
243
Благодарностей
76
Баллы
28
Может кто знает есть ли смысл использовать utf8mb4 вместо родного utf8?
В мане мускула пишут что utf8 они скоро исключат из сборки.
 

bigloafer

Client
Регистрация
23.07.2020
Сообщения
243
Благодарностей
76
Баллы
28
79390


Ни кто не сталкивался с такой ошибкой?

Сам спросил сам решил. О самой проблеме. О способе решения.
Еще пишут, что можно было бы использовать стандартный коннектор - но как его использовать я не знаю :-)
 
Последнее редактирование:

Putn1k

Client
Регистрация
03.01.2020
Сообщения
67
Благодарностей
19
Баллы
8
Добрый день, ребят подскажите, пожалуйста. Что именно в общий код нужно добавить и куда, чтобы если оборвалась связь, он не выдавал ошибку при попытке соединиться с базой, а делал новое подключение и выполнял запрос? Буду очень благодарен за помощь, а то уже задолбался, не могу никак найти.

Всё разобрался с помощью знакомого, вот как это работает на примере метода GetRow

Вставляем этот код в начало метода (не забудьте перезапустить проект после этого, чтобы заработало).

C#:
if ( conn.State != ConnectionState.Open ){
    open();   
}
Вот как это выглядит в общем коде

C#:
public List<string> getRow(string query){
if ( conn.State != ConnectionState.Open ){
    open();   
}
            MySqlCommand command = new MySqlCommand(query, conn);     
      
            MySqlDataReader reader = command.ExecuteReader();
      
      
            if ( reader.Read() ){
        
        List<string> result = new List<string>();
        for(int i=0; i<reader.FieldCount; i++)
        result.Add(reader[i].ToString());

              reader.Close();
        return result;       
            }
          
      reader.Close();
      return new List<string>(); 
    }
 
Последнее редактирование:

bitardenko

Client
Регистрация
27.12.2020
Сообщения
91
Благодарностей
73
Баллы
18
1) посмотреть в конфиге mysql сколько вообще одновременных подключений разрешено - параметр max_connections
2) выставить в конфеге mysql достаточный wait_timeout - возможно сервер банально разрывает соединение из-за того что нет активности
3) дописать в методы getOne, getRow, getAll, query проверку на валидность соединения перед их выполнением и если не валидно - опять делать open

примерно так
C#:
if ( conn.State != ConnectionState.Open ){
    open();  
}
Дописал везде этот код. Имею один кубик, открывающий соединение и второй, берущий его из контекста и делающий запрос. Проблема в том, что если сервер разорвал соединение по таймауту, второй кубик выдаст ошибку. Однако, если после ошибки тут же снова его запустить, он отработает как надо. Это нормальное поведение этого кода? Как я понял методом тыка, до возникновение ошибки вызванной ExecuteNonQuery или Read, он всегда считает, что соединение открыто и open() просто не срабатывает.

В итоге сделал через try/catch как-то так
C#:
        public void query(string query){
            if ( conn.State != ConnectionState.Open ){
                open(); 
            }
            try{
                MySqlCommand command = new MySqlCommand(query, conn);
                command.ExecuteNonQuery();
            }
            catch (MySqlException ex){
                open();
                
                MySqlCommand command = new MySqlCommand(query, conn);
                command.ExecuteNonQuery();
                
            }
        }
Вроде бы работает как надо, но возможно это не лучший вариант или так делать вообще нельзя, я просто не знаю c#
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 719
Баллы
113
Дописал везде этот код. Имею один кубик, открывающий соединение и второй, берущий его из контекста и делающий запрос. Проблема в том, что если сервер разорвал соединение по таймауту, второй кубик выдаст ошибку. Однако, если после ошибки тут же снова его запустить, он отработает как надо. Это нормальное поведение этого кода? Как я понял методом тыка, до возникновение ошибки вызванной ExecuteNonQuery или Read, он всегда считает, что соединение открыто и open() просто не срабатывает.

В итоге сделал через try/catch как-то так
C#:
        public void query(string query){
            if ( conn.State != ConnectionState.Open ){
                open();
            }
            try{
                MySqlCommand command = new MySqlCommand(query, conn);
                command.ExecuteNonQuery();
            }
            catch (MySqlException ex){
                open();
               
                MySqlCommand command = new MySqlCommand(query, conn);
                command.ExecuteNonQuery();
               
            }
        }
Вроде бы работает как надо, но возможно это не лучший вариант или так делать вообще нельзя, я просто не знаю c#
а что будет если ошибка вылетит на команде command.ExecuteNonQuery(); которая находится в блоке catch ?
 

bitardenko

Client
Регистрация
27.12.2020
Сообщения
91
Благодарностей
73
Баллы
18

bigloafer

Client
Регистрация
23.07.2020
Сообщения
243
Благодарностей
76
Баллы
28
В душе не чаю, поэтому и спрашиваю может есть варианты получше.
Пробовал разрывать соединение?
И потом через делать запрос в методе которого есть вот такой код как ниже?
C#:
if ( conn.State != ConnectionState.Open ) open();
Типо сделать соединение, потом разорвать и только потом сделать запрос, чтобы понимать поднимет соединение метод open или не поднимет ...

Просто если у тебя не поднимет, значит у меня тоже не поднимет соединение.
 

bitardenko

Client
Регистрация
27.12.2020
Сообщения
91
Благодарностей
73
Баллы
18
Пробовал разрывать соединение?
И потом через делать запрос в методе которого есть вот такой код как ниже?
C#:
if ( conn.State != ConnectionState.Open ) open();
Типо сделать соединение, потом разорвать и только потом сделать запрос, чтобы понимать поднимет соединение метод open или не поднимет ...

Просто если у тебя не поднимет, значит у меня тоже не поднимет соединение.
Да, если закрывать по db.close(), то поднимает без проблем. Но только в чем смысл? Проще тогда открывать/закрывать соединение в рамках каждого кубика.
Если соединение разорвал сервер, то до возникновение ошибки код в любом случае считает, что соединение есть.
 

bitardenko

Client
Регистрация
27.12.2020
Сообщения
91
Благодарностей
73
Баллы
18
del
 
Последнее редактирование:

LiMe

Client
Регистрация
10.12.2015
Сообщения
618
Благодарностей
339
Баллы
63
C#:
Выполнение действия CSharp OwnCode: DB Open. [Общий код: Строка: 381; Cтолбец: 2] Не удалось загрузить файл или сборку "MySql.Data, Version=6.9.6.0, Culture=neutral, PublicKeyToken=null" либо одну из их зависимостей. Найденное определение манифеста сборки не соответствует ссылке на сборку. (Исключение из HRESULT: 0x80131040)
Подскажите пожалуйста, в чем проблема, подключал уже и из папки Progs и тот что у меня был, не хочет почему-то заводиться, хотя месяцев 6 назад, все без проблем работало. Версия 7.4.0.0
 

Rimen

Client
Регистрация
28.10.2019
Сообщения
406
Благодарностей
253
Баллы
63
C#:
List<string> data = db.getAll("SELECT id, first_name, last_name FROM accounts WHERE status=0 ORDER BY check_time LIMIT 100","|");
Прошу простить мне моё c# невежество. подскажите пожалуйста как это же действие совершить для списка проекта (вместо временного списка "data " внутри кубика)?

можно, конечно, пойти костыльным путем и сначала собрать во временный список, потом каждый элемент временного списка положить в список проекта таким костылем:

C#:
//получаю данные во временный список внутри кубика
List<string> data = db.getAll("SELECT id, first_name, last_name FROM accounts WHERE status=0 ORDER BY check_time LIMIT 100","|");

//прохожусь по временному списку и каждый элемент складываю в список локальный список проекта
for (int i = 0; i < data.Count; i++)
{  
    project.Lists["мой_список"].Add(data[i]);
}

но это как-то уж совсем не изящное решение получается :ah:
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 719
Баллы
113
C#:
List<string> data = db.getAll("SELECT id, first_name, last_name FROM accounts WHERE status=0 ORDER BY check_time LIMIT 100","|");
Прошу простить мне моё c# невежество. подскажите пожалуйста как это же действие совершить для списка проекта (вместо временного списка "data " внутри кубика)?

можно, конечно, пойти костыльным путем и сначала собрать во временный список, потом каждый элемент временного списка положить в список проекта таким костылем:

C#:
//получаю данные во временный список внутри кубика
List<string> data = db.getAll("SELECT id, first_name, last_name FROM accounts WHERE status=0 ORDER BY check_time LIMIT 100","|");

//прохожусь по временному списку и каждый элемент складываю в список локальный список проекта
for (int i = 0; i < data.Count; i++)
{ 
    project.Lists["мой_список"].Add(data[i]);
}

но это как-то уж совсем не изящное решение получается :ah:
project.Lists["мой_список"].AddRange(data );
 
  • Спасибо
Реакции: Rimen и bas2006

bas2006

Client
Регистрация
27.12.2017
Сообщения
40
Благодарностей
3
Баллы
8
Хотелось бы от опытных мнение, в каких ситуациях нужно применять лок не всей таблицы, а только взятой строки в innodb с помощью SELECT … FOR UPDATE (источник), правильно я понимаю что это нужно применять когда много тысяч потоков запущено, а для простых юзеров до 1000 потоков хватит и лок всей таблицы? вообще какой предел примерно по потокам при локе всей таблицы?
 

Rimen

Client
Регистрация
28.10.2019
Сообщения
406
Благодарностей
253
Баллы
63
Нашел в чем был косяк.
Обратил внимание что тем далее обрабатывается БД (а уже до 2 млн. записи дошло), то процесс mysql все более процессор загружает и обработка медленнее идет.
Начал копать и вычитал. Попробовал сделать совмещенный индекс для двух полей по которым отбирается строка. И прям полетело o_O :D
ЗА 2 суток миллион пролетел, а до этого 2,2 млн. за 20 дней :dl:;-):D:D:D
по комменту не очень очевидно. Мне как юзеру который только осваивает SQL пришлось пол часика погуглить пока нашел нужные данные, поэтому позволю себе дополнить Ваш комент:
смотреть нужно в эту сторону.
без индекса логика с парой сотен тысяч запросов в БД работали 5 часов пока не получил ошибку "Connection must be valid and open". После индексирования двух полей в которых производится поиск эта же логика отработала минут за 20 :D:D:D
 
Последнее редактирование:
  • Спасибо
Реакции: seodamage и Koqpe

Sardol

Client
Регистрация
23.09.2020
Сообщения
194
Благодарностей
45
Баллы
28
Последнее редактирование:

Shining

Client
Регистрация
25.05.2018
Сообщения
35
Благодарностей
0
Баллы
6
C#:
Выполнение действия CSharp OwnCode: DB Open. [Общий код: Строка: 381; Cтолбец: 2] Не удалось загрузить файл или сборку "MySql.Data, Version=6.9.6.0, Culture=neutral, PublicKeyToken=null" либо одну из их зависимостей. Найденное определение манифеста сборки не соответствует ссылке на сборку. (Исключение из HRESULT: 0x80131040)
Подскажите пожалуйста, в чем проблема, подключал уже и из папки Progs и тот что у меня был, не хочет почему-то заводиться, хотя месяцев 6 назад, все без проблем работало. Версия 7.4.0.0
Такая же проблема появилась как решил открыть шаб на последних зенках(( Пока не разобрался как фиксить, сижу на старой версии 7.1.6.1 - всё норм.
 

Wide

Client
Регистрация
04.02.2013
Сообщения
945
Благодарностей
257
Баллы
63
Спрашивали тут как взять случайную строку из таблицы.
Вообще, для этих целей есть специальная функция - RAND, т.е запрос должен выглядеть примерно так:
SQL:
SELECT id, name FROM accounts WHERE status=0 ORDER BY RAND() LIMIT 1
Однако, не вдаваясь в подробности могу сказать что RAND() это очень тяжелая функция, и прежде чем выбрать 1 случайную строку MySQL в любом случае "пробежится" по всем строкам таблицы, что как вы понимаете не есть хорошо с точки зрения производительности. Особенно это будет заметно на больших таблицах.
Впрочем, есть другой способ, он состоит из 2х запросов к таблице, но зато оба эти запроса очень простые и не создают ненужной нагрузки.
1. Узнаем общее кол-во интересуемых нас строк в таблице
2. Генерим на c# случайное число от 0 до числа полученного в первом пункте (не включая само число)
3. Берем 1 строку из таблицы со смещением полученным в пункте 2

Вот так это может выглядеть используя предлагаемую в этой теме заготовку:

C#:
int rows_count = int.Parse(db.getOne("SELECT COUNT(*) FROM accounts WHERE status=0"));
if ( rows_count > 0 ){
   string z = Global.Classes.rnd.Next(0,rows_count).ToString();
   var row = db.getRow("SELECT id, name FROM accounts WHERE status=0 LIMIT "+z+",1");
   // row[0] - id
   // row[1] - name
}
else {
   project.SendInfoToLog("Таблица не содержит нужных нам строк",true);
}
Ох и жручая сука до ресурсов, на таблице в 2,5 гб так и не дождался подсчета, стандартным кубиком около 2 сек. Лучше блокировкой обычным селектом миллисекунды займет. Тс спасибо за заготовку огромное!
 

Wide

Client
Регистрация
04.02.2013
Сообщения
945
Благодарностей
257
Баллы
63
Вот что делает блокировка, и ни каких тебе дублей. Это чтение и запись в одну базу. Так как всё упиралось в запуски новых потоков, пришлось зациклить энное количество в одном шаблоне. Сильно зависит от скорости диска, можно еще разнести базы по разным дискам.

Screenshot_72.png
 

Кто просматривает тему: (Всего: 4, Пользователи: 0, Гости: 4)