2 место Работа с MySql в многопотоке. Блокировка таблиц. Получение id добавленной записи.

eee

Client
Регистрация
04.06.2018
Сообщения
134
Благодарностей
31
Баллы
28
немного не понял - в статье используется PHP код, а как его использовать в ZP?
 

Vvafel

Client
Регистрация
24.12.2017
Сообщения
80
Благодарностей
35
Баллы
18
  • Спасибо
Реакции: eee

alex1988

Client
Регистрация
13.07.2014
Сообщения
379
Благодарностей
158
Баллы
43
Добрый вечер подсскажите как задать в данном коде обозначение програмы - а то когда через этот код то none, а когда через кубик зенно то zennoposter.exe??
83125
 
Регистрация
23.03.2015
Сообщения
1 218
Благодарностей
751
Баллы
113
Ребята что я делаю неправильно?
C#:
Sql sqlConn = new Sql(project); //Подключаемся к БД
var cmd = sqlConn.Cmd();

cmd.Connection.Open();

//Блокируем таблицы:
cmd.DbLock($"wp_edit WRITE");
//проверяем наличие заданий к выполнению (со статусом "0"):
var reader = cmd.ExReader(String.Format("SELECT id, status FROM wp_edit WHERE url='2' AND login='4' AND pass='5' LIMIT 1;"));
if(reader.HasRows) //проверяем имеются ли данные в ответе. Если имеются, то переходим к считыванию
{
    while (reader.Read()) // построчно в цикле (while) считываем данные. Получим максимум 1 строку, т.к. в запросе стоит LIMIT 1
    {
        string dbId = reader["id"].ToString();
        string dbSt = reader["status"].ToString();
    
        dbId = project.Variables["id"].Value;
        dbSt = project.Variables["status"].Value;
        
        project.SendInfoToLog(string.Format("id: {0} st:{1}", dbId, dbSt), true);
    }
}
reader.Close();

cmd.DbUnLock(); //разблокировка всех таблиц
cmd.Connection.Close(); //закрываем сессию
Простейший запрос, планировал потратить на него пару минут а мучаюсь второй день(
Код отрабатывает нормально, но переменные остаются пустыми в лог выводится "id: st: "
В панеле базы данных запрос отрабатывает корректный

Сама таблица выглядит так:
86742

Выручайте!
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 720
Баллы
113
Ребята что я делаю неправильно?
C#:
Sql sqlConn = new Sql(project); //Подключаемся к БД
var cmd = sqlConn.Cmd();

cmd.Connection.Open();

//Блокируем таблицы:
cmd.DbLock($"wp_edit WRITE");
//проверяем наличие заданий к выполнению (со статусом "0"):
var reader = cmd.ExReader(String.Format("SELECT id, status FROM wp_edit WHERE url='2' AND login='4' AND pass='5' LIMIT 1;"));
if(reader.HasRows) //проверяем имеются ли данные в ответе. Если имеются, то переходим к считыванию
{
    while (reader.Read()) // построчно в цикле (while) считываем данные. Получим максимум 1 строку, т.к. в запросе стоит LIMIT 1
    {
        string dbId = reader["id"].ToString();
        string dbSt = reader["status"].ToString();
   
        dbId = project.Variables["id"].Value;
        dbSt = project.Variables["status"].Value;
       
        project.SendInfoToLog(string.Format("id: {0} st:{1}", dbId, dbSt), true);
    }
}
reader.Close();

cmd.DbUnLock(); //разблокировка всех таблиц
cmd.Connection.Close(); //закрываем сессию
Простейший запрос, планировал потратить на него пару минут а мучаюсь второй день(
Код отрабатывает нормально, но переменные остаются пустыми в лог выводится "id: st: "
В панеле базы данных запрос отрабатывает корректный

Сама таблица выглядит так:
Посмотреть вложение 86742
Выручайте!
так ты же их затираешь....

86743
 
  • Спасибо
Реакции: KolkaPetkinSyn
Регистрация
23.03.2015
Сообщения
1 218
Благодарностей
751
Баллы
113

p-sergei

Client
Регистрация
20.12.2016
Сообщения
543
Благодарностей
263
Баллы
63
  • Спасибо
Реакции: KolkaPetkinSyn и Phoenix78
Регистрация
23.03.2015
Сообщения
1 218
Благодарностей
751
Баллы
113
  • Спасибо
Реакции: p-sergei

legorange

Client
Регистрация
22.04.2020
Сообщения
13
Благодарностей
34
Баллы
13
Mysql like works queue,
Multiple queries at the same time

SQL:
BEGIN
SET @v1 = (
SELECT id_table FROM table WHERE process_task = 0 AND date_start IS NULL LIMIT 1 FOR UPDATE)
UPDATE table SET process_task = 1,date_start = now() WHERE id_table = @v1
Select @v1
COMMIT
The query returns the id to work, once obtained and blocked, do. . .

Tables: InnoDB
Mysql: 5.7

Connection String must included: allowuservariables=True

86880
 
  • Спасибо
Реакции: volody00

Livesferma

Client
Регистрация
22.10.2020
Сообщения
32
Благодарностей
3
Баллы
8
К сожалению я не научу вас делать такие комбайны. Но постараюсь направить вас в нужное русло. Многие из вас уже работают с БД. Надеюсь у меня получится объяснить вам как работать с БД в многопотоке. И если вам что-то будет не понятно, не отчаивайтесь и не пугайтесь - учитесь. Помните: если идете как все, то и зарабатываете как все.
Многие уже много лет сидят на кубиках, даже не пробуя С#. Пора бы уже поменять свой подход к работе. Поверьте, результаты не заставят себя долго ждать.

Работа с БД выглядит примерно следующим образом:
  1. Подключение к БД
  2. Открытие сессии
  3. Выполнение произвольного количества запросов
  4. Закрытие сессии
Особенность работы стандартными методами зенки в том, что она упрощает для пользователя всю эту работу, но в тоже время и сильно его ограничивает.

Зенка все эти действия выполняет одной строчкой. Это просто. Но если нам надо выполнить множество запросов в рамках одной сессии, то у нас это не получится.

Т.к. каждый новый вызов метода будет снова открывать новую сессию, выполнять запрос и закрывать сессию.

Поэтому мы не можем блокировать таблицы, не можем работать с многопотоком, не можем получить id только что вставленной записи в многопотоке, чтобы использовать этот id для добавления записи в другую таблицу.

Что же делать? Можно использовать костыли: 1 2 3 4 5

А можно обратиться к стандартной библиотеке для работы с MySql и научиться с ней работать. А чтобы крыша не ехала от обилия строчек в коде - даже упростить всю работу в простые методы одной строкой.

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

Подключаемся к БД двумя короткими строчками:
PHP:
Sql sqlConn = new Sql(project);
var cmd = sqlConn.Cmd();
Далее открываем сессию:
PHP:
cmd.Connection.Open();
в рамках которой и будем отправлять все запросы. Каждый поток работает в рамках своей сессии.

Если таблица заблокирована (об этом позже), то поток ждет, когда её разблокируют и уже в порядке очереди работает с ней.

Перед каждым запросом мы в свойство cmd.CommandText кладем сам запрос:
PHP:
cmd.CommandText = "SELECT id FROM phone WHERE phone='79808786445' LIMIT 1;";
Далее выполняем его:
PHP:
cmd.ExecuteScalar();
В данном случае выполняется скалярный запрос, который возвращает одну строку состоящую из одного столбца. Короче говоря возвращает ячейку таблицы.

Чтобы выполнить запрос без ответа:
PHP:
cmd.CommandText=String.Format("UPDATE advert SET status='busy' WHERE id={0};", idadvert);
cmd.ExecuteNonQuery();
Таким запросом можно добавить запись в БД.

Если мы хотим добавить запись и получить id только что добавленной записи, то мы должны выполнить еще один запрос:
PHP:
"SELECT last_insert_id();"
В итоге добавление + получение id будет выглядеть так:
PHP:
cmd.CommandText = "INSERT INTO advertise SET text='Тестовый текст'";
cmd.ExecuteNonQuery();
cmd.CommandText = @"SELECT last_insert_id();";
cmd.ExecuteScalar();
Получить данные из таблицы:
PHP:
cmd.CommandText = String.Format("SELECT * FROM advertise ORDER BY id DESC LIMIT 5;");
var reader = cmd.ExecuteReader();
Перед тем как начать считывать данные из reader методом .Read() (reader.Read()) необходимо убедиться, что данные вообще имеются в reader, иначе будет исключение (ошибка).

Проверка делается следующим образом:
if(reader.HasRows) - свойство HasRows объекта reader возвращает либо true либо false. Если true - значит данные имеются и можно начинать считывание:
PHP:
while (reader.Read())
{
    string dbId = reader["id"].ToString();
    string dbText = reader["text"].ToString();
    string dbPhone = reader["phone"].ToString();

    project.SendInfoToLog(string.Format("id: {0}, text: {1}, phone: {2}", dbId, dbText, dbPhone));
}
Данные считываются в цикле while. Т.е. перебирается строчка за строчкой пока не закончатся строки.

reader["id"] - id - название столбца в таблице. Т.к. данные из reader считываются как тип object, то их необходимо привести к нужному нам типу. В данном случае string, но вы можете конвертировать объект в любой тип данных: число, строка, время, дата и т.д. Например:
PHP:
Convert.ToInt64(reader["phone"])
Полученные данные сохраняйте в переменные, таблицы, списки и т.д.



Если выполнили все запросы, то закрывайте сессию:
PHP:
cmd.Connection.Close();
Расширения методов
Когда вам нужно на одно действие писать как минимум 2 строки (а порой и 4), то очень скоро от обилия всего этого многообразия начинает пухнуть голова и начинаешь путаться.

Поэтому с помощью расширений о которых писали в предыдущем конкурсе я немного упростил работу, сделав всё одной строкой:
PHP:
object o = cmd.ExScalar(scalarQuery); //Скалярный запрос
int i = cmd.ExNonQ(nonQuery); //Запрос без ответа
long l = cmd.ExQWithLastID(withIdQuery); //Запрос, в ответе которого получаем ID добавленной записи.
var reader = cmd.ExReader(readQuery); //Запрос, в ответе которого получаем строки данных
Обратите внимание, что скалярный запрос cmd.ExScalar() возвращает тип object, поэтому если хотите получить какой-то конкретный ответ, то результаты конвертируйте в нужный вам тип данных:
PHP:
Convert.ToDouble();
Convert.ToString();
Convert.ToBoolean();
Convert.ToInt64();
и т.д...
Пример:
PHP:
bool o = Convert.ToBoolean(cmd.ExScalar(scalarQuery));
Пожалуйста скиньте файл \Progs\ExternalAssemblies\RECAPTCHASOLUTION.DLL буду очень благодарен
 

ShikoFess

Client
Регистрация
21.12.2017
Сообщения
146
Благодарностей
116
Баллы
43
ищи в гугле индексирование таблиц mysql
также изучи курс, который я рекомендовал ранее https://geekbrains.ru/courses/86 можешь поискать на торрентах. там как раз узнаешь про объединение таблиц
А как называется этот курс? А то по ссылке редирект на главную страницу идет
P.S.: Нашел курс, называется [Geekbrains] Основы баз данных (2020) Ссылка https://cloud.mail.ru/public/ge9P/zk27zvR4q
 
Последнее редактирование:
  • Спасибо
Реакции: genri и morgansho

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