• Программинг

Нужны источники бесперебойного питания?

Источники бесперебойного питания от дизельстор

С# Пишем DELETE для SQLite. Часть 3

Продолжаем писать библиотеку быстрого доступа для новых программ под SQLite. В первых двух частях (здесь и здесь) были описаны операции SELECT и INSERT. Сегодня, на ваш суд, я представляю код для операции DELETE. Операция жесткая… Пользоваться аккуратно. Можно остаться без данных, а может и без пальцев ;) , смотря какие данные завалить.

Исходя из нашей философии написания этого класса, мудрить сильно не будем. Я представлю вам реализацию трех методов, которые удаляют данные. Два из них простых, один немного сложнее, но интереснее.
Реализация

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

1 public int Delete(string tablename)
2 public int Delete(string tablename, string where)
3 public int Delete(string tablename, string column, object[] collection)

Первые два метода похожи. Отличие только в том, что второй принимает условие, наряду с названием таблицы. Вот часть кода, которая отвечает за выполнение запроса:

1 string sql = string.Format("DELETE FROM {0} {1}", tablename, where);
2 ...
3 SQLiteCommand command = new SQLiteCommand(sql, connect);
4 command.ExecuteNonQuery();

Здесь, как мы видим все просто. Но существуют такие ситуации, когда записей, которых необходимо удалить, много. И они находятся в разных местах таблицы. Каждый раз посылать запрос на удаление одной записи нелогично, т.к. это занимает много времени. Каждый раз происходит подключение и отключение от базы, а это требует времени. Рассмотрим код, который работает нерационально, используя наш второй метод:

1 foreach (DataGridViewRow row in grdMain.SelectedRows)
2 {
3     db.Delete("test", "WHERE id = " + row.Cells[0].Value;
4 }

В цикле мы проходим по всем выделенным строкам и каждую удаляем. Если 2-3 строки, то работает незаметно, но если их хотя бы 100 и больше – появляются задержки.

Решение проблемы лежит в одном запросе, который содержит условия для всех удаляемых строк. В блоке условий WHEREперечисляем все наши условия разделяя их оператором OR. Тогда запрос выглядит следующим образом:

1 DELETE FROM test WHERE id = 1 OR id = 2 OR id = 100

Думаю, что с этим все понятно. Теперь сам метод, в котором описана методика построения строки запроса:

1 public int Delete(string tablename, string column, object[] collection)
2 {
3     ConnectionState previousConnectionState = ConnectionState.Closed;
4     using (SQLiteConnection connect = new SQLiteConnection(ConnectionString))
5     {
6         try
7         {
8             previousConnectionState = connect.State;
9             if (connect.State == ConnectionState.Closed)
10             {
11                 connect.Open();
12             }
13             #region Создаем строку условий
14             bool ifFirst = true;
15             string where = string.Empty;
16             foreach (object item in collection)
17             {
18                 if (ifFirst)
19                 {
20                     where = "WHERE " + column + " = '" + item + "'";
21                     ifFirst = false;
22                 }
23                 else
24                 {
25                     where += " OR " + column + " = '" + item + "'";
26                 }
27             }
28             #endregion
29  
30             string sql = string.Format("DELETE FROM {0} {1}", tablename, where);
31             SQLiteCommand command = new SQLiteCommand(sql,connect);
32             command.ExecuteNonQuery();
33         }
34         catch (Exception error)
35         {
36             System.Windows.Forms.MessageBox.Show(error.Message, "Ошибка при удалении данных из таблицы " + tablename, MessageBoxButtons.OK, MessageBoxIcon.Error);
37             return 1;
38         }
39         finally
40         {
41             if (previousConnectionState == ConnectionState.Closed)
42             {
43                 connect.Close();
44             }
45         }
46         return 0;
47     }
48 }

Этот метод принимает имя таблицы, имя поля, по которому идет проверка условий, и массив самих условий. В цикле foreach проходим по всем объектам и строим строку, разделяя ее оператором OR. Таким образом в сам метод можно передавать любой массив. Примеры вызова этого метода:

1 dbFacade db = new dbFacade();
2 db.Delete("test", "id", new string[] {"1","2","100","200"});
3 db.Delete("test", "id", new int[] {1,2,100,200});
4 ArrayList list = new ArrayList();
5 list.Add(1);
6 list.Add(2);
7 list.Add(100);
8 db.Delete("test", "id", list.ToArray());

Исходя из этого мы можем передавать любой массив объектов, каждый элемент которого можно представить в виде строки. Все три метода возвращают целое число. Если операция удаления прошла успешно, возвращается 0. В остальных случаях код ошибки, который вы можете придумать сами.

Заключение

Вот и разобрали операцию DELETE. Если у вас появятся, какие-либо полезные идеи, пишите мне.
Как обычно вы можете скачать тестовый проект
Прямая ссылка на текущую версию dbFacade.