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

  • Автор темы Автор темы WebBot
  • Дата начала Дата начала
  • Теги Теги
    mysql
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";
 
Вот в логах видно обрывается соединение на 60 секунде и не понимаю как увеличить его
73773


В проджекте такая ошибка: "Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding."
 
WebBot, огромнейшее вам спасибо за статью)) Благодаря ей, узнал все основные принципы в работе с mysql и отказался во всех проектах, от таблиц и списков. Также начал собирать большую часть проектов на C#, хотя в нем вообще не разбираюсь и не изучал :D А сейчас и с циклами, и с условиями проверки спокойно оперирую :-) Все благодаря вашей статье с хорошим инструкциями.
Итог: Изучал статью для работы с mysql, а начал ещё и в c# разбираться (основы по крайней мере):D
 
Всем привет, при взятии строки выходит такая ошибка: Выполнение действия CSharp OwnCode: взять аккаунт. [Строка: 31; Cтолбец: 0] Выдано исключение типа "System.Exception". Подскажите в какую сторону копать?

P.S. Разобрался.
 
Последнее редактирование:
В гугл таблицах есть функция "Вставить изображение в ячейку". Подскажите как можно сделать тоже самое в зенопостере? Возможно через HttpPost запрос?

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

Вложения

  • Screenshot_1.png
    Screenshot_1.png
    43,5 KB · Просмотры: 327
@zenno.xxx
Судя по всему не может найти класс DB который в заготовке находится в общем коде.
1. Вы используете заготовку с уже включенным в общий код классом?
2. MySql.Data.dll скопирован для вашей версии ZP из папки Progs в папку ExternalAssemblies ?
Я сделал все как написано и не работает! DB он не может найти! Подскажите - где то что такое простое, потому что не видит он DB
 
DB db = new DB(db_host, db_user, db_pswd, db_database, db_charset);
Не работает! Добавил файл как описано! В кубике создаю экземпляр класса DB и он его не видит! В чем секрет?
 
Я сделал все как написано и не работает!
Сделал бы все как написано, все бы работало, возьми прикрепленный к первому посту шаблон с примером и подставь свои данные.
 
Тип Время Сообщение
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]
 
Понятно, легких путей не ищешь...
 
Нашел - спасибо, нужно было создать публичный класс DB и поехало. Спасибо!
 
  • Спасибо
Реакции: Koqpe
Может кто знает есть ли смысл использовать utf8mb4 вместо родного utf8?
В мане мускула пишут что utf8 они скоро исключат из сборки.
 
79390


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

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

Всё разобрался с помощью знакомого, вот как это работает на примере метода 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>(); 
    }
 
Последнее редактирование:
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#
 
Дописал везде этот код. Имею один кубик, открывающий соединение и второй, берущий его из контекста и делающий запрос. Проблема в том, что если сервер разорвал соединение по таймауту, второй кубик выдаст ошибку. Однако, если после ошибки тут же снова его запустить, он отработает как надо. Это нормальное поведение этого кода? Как я понял методом тыка, до возникновение ошибки вызванной 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 ?
 
В душе не чаю, поэтому и спрашиваю может есть варианты получше.
Пробовал разрывать соединение?
И потом через делать запрос в методе которого есть вот такой код как ниже?
C#:
Развернуть Свернуть Копировать
if ( conn.State != ConnectionState.Open ) open();

Типо сделать соединение, потом разорвать и только потом сделать запрос, чтобы понимать поднимет соединение метод open или не поднимет ...

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

Типо сделать соединение, потом разорвать и только потом сделать запрос, чтобы понимать поднимет соединение метод open или не поднимет ...

Просто если у тебя не поднимет, значит у меня тоже не поднимет соединение.
Да, если закрывать по db.close(), то поднимает без проблем. Но только в чем смысл? Проще тогда открывать/закрывать соединение в рамках каждого кубика.
Если соединение разорвал сервер, то до возникновение ошибки код в любом случае считает, что соединение есть.
 
del
 
Последнее редактирование:
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
 
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:
 
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
Хотелось бы от опытных мнение, в каких ситуациях нужно применять лок не всей таблицы, а только взятой строки в innodb с помощью SELECT … FOR UPDATE (источник), правильно я понимаю что это нужно применять когда много тысяч потоков запущено, а для простых юзеров до 1000 потоков хватит и лок всей таблицы? вообще какой предел примерно по потокам при локе всей таблицы?
 
Нашел в чем был косяк.
Обратил внимание что тем далее обрабатывается БД (а уже до 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
Последнее редактирование:
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 - всё норм.
 
Спрашивали тут как взять случайную строку из таблицы.
Вообще, для этих целей есть специальная функция - 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 сек. Лучше блокировкой обычным селектом миллисекунды займет. Тс спасибо за заготовку огромное!
 
Вот что делает блокировка, и ни каких тебе дублей. Это чтение и запись в одну базу. Так как всё упиралось в запуски новых потоков, пришлось зациклить энное количество в одном шаблоне. Сильно зависит от скорости диска, можно еще разнести базы по разным дискам.

Screenshot_72.png
 

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