К сожалению я не научу вас делать такие комбайны. Но постараюсь направить вас в нужное русло. Многие из вас уже работают с БД. Надеюсь у меня получится объяснить вам как работать с БД в многопотоке. И если вам что-то будет не понятно, не отчаивайтесь и не пугайтесь - учитесь. Помните: если идете как все, то и зарабатываете как все.
Многие уже много лет сидят на кубиках, даже не пробуя С#. Пора бы уже поменять свой подход к работе. Поверьте, результаты не заставят себя долго ждать.
Работа с БД выглядит примерно следующим образом:
- Подключение к БД
- Открытие сессии
- Выполнение произвольного количества запросов
- Закрытие сессии
Особенность работы стандартными методами зенки в том, что она упрощает для пользователя всю эту работу, но в тоже время и сильно его ограничивает.
Зенка все эти действия выполняет одной строчкой. Это просто. Но если нам надо выполнить множество запросов в рамках одной сессии, то у нас это не получится.
Т.к. каждый новый вызов метода будет снова открывать новую сессию, выполнять запрос и закрывать сессию.
Поэтому мы не можем блокировать таблицы, не можем работать с многопотоком, не можем получить id только что вставленной записи в многопотоке, чтобы использовать этот id для добавления записи в другую таблицу.
Что же делать? Можно использовать костыли:
1 2 3 4 5
А можно обратиться к стандартной библиотеке для работы с MySql и научиться с ней работать. А чтобы крыша не ехала от обилия строчек в коде - даже упростить всю работу в простые методы одной строкой.
Чем меньше кода перед глазами, тем проще. Особенно - для новичков.
Поэтому подключение к БД я вывел в общий код. Данные доступа к БД - в настройки.
Подключаемся к БД двумя короткими строчками:
Sql sqlConn = new Sql(project);
var cmd = sqlConn.Cmd();
Далее открываем сессию:
в рамках которой и будем отправлять все запросы. Каждый поток работает в рамках своей сессии.
Если таблица заблокирована (об этом позже), то поток ждет, когда её разблокируют и уже в порядке очереди работает с ней.
Перед каждым запросом мы в свойство
cmd.CommandText кладем сам запрос:
cmd.CommandText = "SELECT id FROM phone WHERE phone='79808786445' LIMIT 1;";
Далее выполняем его:
В данном случае выполняется скалярный запрос, который возвращает одну строку состоящую из одного столбца. Короче говоря возвращает ячейку таблицы.
Чтобы выполнить запрос без ответа:
cmd.CommandText=String.Format("UPDATE advert SET status='busy' WHERE id={0};", idadvert);
cmd.ExecuteNonQuery();
Таким запросом можно добавить запись в БД.
Если мы хотим добавить запись и получить id только что добавленной записи, то мы должны выполнить еще один запрос:
"SELECT last_insert_id();"
В итоге добавление + получение id будет выглядеть так:
cmd.CommandText = "INSERT INTO advertise SET text='Тестовый текст'";
cmd.ExecuteNonQuery();
cmd.CommandText = @"SELECT last_insert_id();";
cmd.ExecuteScalar();
Получить данные из таблицы:
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 - значит данные имеются и можно начинать считывание:
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, но вы можете конвертировать объект в любой тип данных: число, строка, время, дата и т.д. Например:
Convert.ToInt64(reader["phone"])
Полученные данные сохраняйте в переменные, таблицы, списки и т.д.
Если выполнили все запросы, то закрывайте сессию:
Расширения методов
Когда вам нужно на одно действие писать как минимум 2 строки (а порой и 4), то очень скоро от обилия всего этого многообразия начинает пухнуть голова и начинаешь путаться.
Поэтому с помощью расширений
о которых писали в предыдущем конкурсе я немного упростил работу, сделав всё одной строкой:
object o = cmd.ExScalar(scalarQuery); //Скалярный запрос
int i = cmd.ExNonQ(nonQuery); //Запрос без ответа
long l = cmd.ExQWithLastID(withIdQuery); //Запрос, в ответе которого получаем ID добавленной записи.
var reader = cmd.ExReader(readQuery); //Запрос, в ответе которого получаем строки данных
Обратите внимание, что скалярный запрос
cmd.ExScalar() возвращает тип
object, поэтому если хотите получить какой-то конкретный ответ, то результаты конвертируйте в нужный вам тип данных:
Convert.ToDouble();
Convert.ToString();
Convert.ToBoolean();
Convert.ToInt64();
и т.д...
Пример:
bool o = Convert.ToBoolean(cmd.ExScalar(scalarQuery));