nik-n
Client
- Регистрация
- 05.11.2016
- Сообщения
- 243
- Благодарностей
- 20
- Баллы
- 18
по C# + SQL - это самая простая и понятная инструкция из всех на форуме!Приветствую!
Ранее я подавал заявку на конкурс статей, где хотел разобрать недостатки стандартного кубика для работы с БД (и получаемого из него кода) и вместе с вами пошагово разразработать в общем коде простейший (без каких-либо наворотов и заумностей) класс для работы с MySQL, позволяющий избежать этих недостатков. Но тогда не сложилось, вторую тему по MySQL не одобрили.
Сейчас конкурс шаблонов, поэтому теорию и пошаговую разработку мы пропустим, а я просто приложу шаблон-заготовку с простейшим классом в общем коде, который позволит избежать серьезных недостатков стандартного кода/кубика и сделать работу с MySQL более приятной.
Недостатки стандартного кубика/кода
Главный минус - нет возможности управлять открытием/закрытием коннектов/сессией. Каждый кубик/код работы с БД устанавливает соединение, открывает новую сессию, выполняет SQL запрос и закрывает сессию.
Отсюда проблемы:
Вдобавок:
- Невозможно выполнить множество запросов в рамках одной сессии с промежуточной обработкой данных. А именно это чаще всего и нужно для нормальной работы в многопотоке.
- Невозможно получить Id только что вставленной записи (повторный вызов кубика/кода откроет новую сессию где этой информации не будет)
- Открытие/закрытие подключений/сессий a) занимает доп. время б) создает доп. нагрузку. Если в шаблоне 50 кубиков работы с БД, то это 50 открытий/закрытий подключений/сессий на 1 поток. А если потоков сотни?
- Отсутствие функции экранирования спецсимволов (это обязательно нужно делать перед вставкой строковых данных в таблицу). Может я плохо искал?
- Насколько я помню код из кубика не хотел работать со списками созданными в C#, а работал только со списками созданными в ZP. Это очень неудобно.
- Код из кубика тяжел для восприятия - этакая сборная солянка из хоста/логина/пароля/бд/параметров подклобчения/sql запроса/прочих параметров
Итак, наша задача - решить описанные выше недостатки и сделать работу с БД MySQL более простой и наглядной.
Использование заготовки:
Подготовка ZP. Идем в директорию куда установлен ZP и в папке Progs находим файл MySql.Data.dll . Копируем его в папку ExternalAssemblies находящуюся там же.
Далее открываем заготовку и в кубике C# пишем: (далее идут примеры):
Итак, пример(ы) кода:
Надеюсь данная заготовка кому-нибудь пригодится и поможет начать работать с MySQL т.к это открывает вам совершенно иные возможности при создании ваших шаблонов!C#:string db_host = "localhost"; // хост string db_user = "root"; // username для подключения к MySQL string db_pswd = ""; // пароль для подключения к MySQL string db_database = "mydb"; // название БД с которой будет работа string db_charset = "utf8"; // кодировка данных в таблицах // коннект к MySQL и открытие сессии DB db = new DB(db_host, db_user, db_pswd, db_database, db_charset); // все что идет ниже выполняется в рамках одного коннекта/сессии ... это очень важно (!) // получить 1 результат (скаляр) // для получения 1 результата всегда используем метод getOne string count = db.getOne("SELECT COUNT(*) FROM accounts WHERE status=0"); project.SendInfoToLog("Кол-во аккаунтов: "+count,true); // выводим в лог ZP // получить 1 запись ( запись = 1 строка разделенная на столбцы ) // для получения 1 записи/строки всегда используем метод getRow List<string> row = db.getRow("SELECT first_name, last_name, status FROM accounts WHERE id=1"); if ( row.Count > 0 ){ project.SendInfoToLog("Имя: "+row[0],true); // выводим в лог ZP project.SendInfoToLog("Фамилия: "+row[1],true); // выводим в лог ZP project.SendInfoToLog("Статус: "+row[2],true); // выводим в лог ZP } else { project.SendInfoToLog("запись отсутствует",true); // выводим в лог ZP } // для запросов не возвращающих результата (INSERT/UPDATE/LOCK/UNLOCK/...) всегда используем метод query // лочим таблицу accounts что бы только 1 поток работал с ней // P.S вы должны лочить все таблицы и их алиасы с которыми собираетесь работать в рамках строго 1 потока .. // в этом примере работа идет лишь с 1 таблицей, поэтому и лочится только она db.query("LOCK TABLES accounts WRITE"); // получить набор строк/столбцов // для получения набора данных всегда используем метод getAll .. второй параметр - разделитель столбцов в строках ... его можно не указывать, по умолчанию он | // берем 100 акков со status=0 (свободные), которые при этом дольше всех не брались ( ORDER BY check_time ) List<string> data = db.getAll("SELECT id, first_name, last_name FROM accounts WHERE status=0 ORDER BY check_time LIMIT 100","|"); List<string> ids = new List<string>(); // в этот список сохраним только id полученных данных for(int i=0; i<data.Count; i++){ var x = data[i].Split('|'); project.SendInfoToLog("ID: "+x[0],true); project.SendInfoToLog("Имя: "+x[1],true); project.SendInfoToLog("Фамилия: "+x[2],true); project.SendInfoToLog("--------------",true); ids.Add(x[0]); // добавляем очередной id в список ids } // текущее юникс-время int unixtime = (int)(DateTime.UtcNow - new DateTime(1970,1,1)).TotalSeconds; // здесь, например, делаем чекинг id из списка ids на онлайн в ВК и наполнztv список online теми id которые сейчас онлайн List<string> online = new List<string>(); // меняем статус у тех кто online (только их мы берем в работу) if ( online.Count > 0 ) db.query("UPDATE accounts SET status=1 WHERE id IN("+string.Join(",",online)+")"); // обновляем время проверки у всех взятых id if ( ids.Count > 0 ) db.query("UPDATE accounts SET check_time="+unixtime.ToString()+" WHERE id IN("+string.Join(",",ids)+")"); // разлочиваем таблицу db.query("UNLOCK TABLES"); // пример экранирования спецсимволов в строке (если не экранировать, то одинарная кавычка поломает наш запрос) string first_name = db.escapeString("Д'артаньян"); // вставка новой записи db.query("INSERT INTO accounts SET first_name='"+first_name+"'"); // получение Id только что вставленной записи string acc_id = db.getOne("SELECT LAST_INSERT_ID()"); project.SendInfoToLog("ID вставленной записи: "+acc_id,true); // завершаем сессию db.close();
К посту приложены 2 файла - mysql_zagotovka.xmlz и primer1.xmlz . В первом файле не реализовывается какая-то конкретная логика, это просто заготовка со встроенным классом + кубик C# с примерами того как используя методы класса коннектиться к БД, делать различные запросы и тд (в общем то же самое что вы видите в примерах в этом посте). Во втором файле (primer1.xmlz) реализована прямо конкретная логика по взятию аккаунтов в работу из БД в многопотоке, там достаточно создать свою таблицу нужной структуры (приведена мной несколькими постами ниже) и подставить свои данные для коннекта к БД. И все, можно юзать в своих проектах!
ps когда на форум добавят кнопку дабл лайк???? )