Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/15: Рейтинг темы: голосов - 15, средняя оценка - 4.73
 Аватар для Сергей1980
547 / 377 / 16
Регистрация: 17.12.2009
Сообщений: 991

Библиотека / класс для универсальной работы с DataGridView

08.02.2020, 20:25. Показов 3130. Ответов 15

Студворк — интернет-сервис помощи студентам
Добрый вечер!
Подскажите пожалуйста, существуют ли универсальные решения (библиотеки) для реализации CRUD операций связки DataGridView и MySql server?
Имею в виду при подключении которых к примеру реализовывались все основные методы взаимодействия datagridview и сервера как есть (инлайн редактирование ячейки с отправкой измененного значения на сервер, удаление строки с зеркальным удалением строки из таблицы на mysql, добавления). То есть CRUD библиотека с автоматической реализацией методов INSERT,UPDATE,DELETE,SELECT? В стиле применил и забыл. На просторах есть решение,но оно платное, к примеру Bunifu

https://www.youtube.com/watch?v=ae0w2gA_M3U

Оно позволяет редактировать грид как есть (по аналогии к примеру с MS Access,Excel).

Есть что то подобное из бесплатных решений?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
08.02.2020, 20:25
Ответы с готовыми решениями:

Создание универсальной функции для работы с элементом управления DataGridView
Здравствуйте, Я работаю на своей любительской программой в целях обучения. На форме 2 DataGridView. В коде много раз повторяются одни и...

Класс/библиотека для работы с БД
Коллеги, подскажите, пожалуйста, какой-нибудь простенький, но продвинутый класс для работы с БД. Чего хотел бы: - передача...

VBA: Библиотека/класс для работы с окнами - ищу
Добрый день! Подскажите, плиз! Столкнулся с работой с окнами в Windows. Изучаю WindowsAPI: FindWindow, GetWindowText,...

15
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
09.02.2020, 13:16
Лучший ответ Сообщение было отмечено Сергей1980 как решение

Решение

Решение на основании DataGridView/DataSet/DataAdapter можно написать за десять минут

Добавлено через 1 минуту
По ссылке нет автоматической реализации, там тоже надо указывать select/update/delete запросы
2
 Аватар для Сергей1980
547 / 377 / 16
Регистрация: 17.12.2009
Сообщений: 991
09.02.2020, 18:07  [ТС]
Я в принципе так и понял. В шарпе новичок. Около недели. Но на update уже в принципе написал универсальный метод, который можно просто накинуть на datagrid view, на событие celleditend, которое не зависит от типа вводимых данных, и ячейки которая правится.
Подскажите пожалуйста, как в шарпе реализовать присвоение встроенных методов к объекту,который передается как аргумент к примеру.
Имею в виду- я пишу собственный класс, который в конструкторе при вызове будет принимать в качестве аргумента datagridview с формы.
Как в классе о наследовать /перезагрузить встроенные методы и связать их с переменной типа datagridview?
Просто указать через нижнее подчеркивание?

Пример простенький:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DatagridViewHandler(){
DataGridView datagridview;
 
//Конструктор
public DatagridViewHandler(DataGridView datagridview){
this.datagridview=datagridview;
}
 
public void datagridview_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
 
}
 
 
}
Как то так? Заранее извиняюсь за регистры, накатал с мобилы.

Добавлено через 13 минут
Это как раз по поводу автоматической реализации.
0
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
09.02.2020, 18:51
Сергей1980, вы наверное имеете ввиду подписку на события?

C#
1
2
3
4
5
6
7
8
public DatagridViewHandler(DataGridView datagridview){
    this.datagridview=datagridview;
    this.datagridview.CellEndEdit += datagridview_CellEndEdit;
}
 
void datagridview_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
}
1
 Аватар для Сергей1980
547 / 377 / 16
Регистрация: 17.12.2009
Сообщений: 991
09.02.2020, 19:04  [ТС]
Да, наверное , это в c# называется так инициализация встроенных методов?
А этот цикл не подвесит излишне систему, он в отдельном потоке выполняется? Извините, пришел из java просто.

То есть как я правильно понял, ваша конструкция инициирует зажигание метода CellEndEdit, когда создаётся экземпляр моего класса и в качестве переменной в него передается datagridview? Если да, то то что нужно, спасибо. Приду домой затестю.
0
 Аватар для Сергей1980
547 / 377 / 16
Регистрация: 17.12.2009
Сообщений: 991
17.02.2020, 23:47  [ТС]
Удалось добраться до доделки универсального обработчика изменяемой ячейки грида. В общем получилось ,то что нужно.
Метод сам определяет тип поля из таблицы MySql. Сопоставляет имя поля с именем текущей ячейки грида и выполняет автоматически запрос на обновление. (Код подписки убрал из примера, он не существенен.)

Сопоставление идет автоматически на событие CellEditEnd. Можкт быть конечно как то поизящней м покороче можно было сделать, но модель рабочая:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                int colInd = dataGridView.CurrentCell.ColumnIndex; // индекс столбца текущей ячейки
                int rowInd = dataGridView.CurrentCell.RowIndex; // индекс строки текущей ячейки
                String colVal = Convert.ToString(dataGridView.CurrentCell.Value); //конвертация любого типа значения ячейки в текст
                String colName = dataGridView.Columns[colInd].Name; // имя текущей ячейки
                String fieldCritValue = dataGridView.Rows[e.RowIndex].Cells[0].Value.ToString(); // значение поля критерия выборки для Where
                //Строка для автоматического определения типа данных поля в таблице MySQL по имени текущей ячейки
                String strSqlDefineType = "SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 't_sales' AND COLUMN_NAME = '" + colName + "'";
                MySqlCommand mySqlCommand = new MySqlCommand(strSqlDefineType, DbConnection.mySqlConnection);
                MySqlDataReader reader = mySqlCommand.ExecuteReader();
                reader.Read();
                string type = reader.GetValue(0).ToString();// принимает тип поля из таблицы MySQL в текстовом виде
                reader.Close();
                if (type == "date")
                {
                    DateTime dateValue = DateTime.Parse(colVal);
                    colVal = dateValue.ToString("yyyy-MM-dd");
                }
                if (type == "double" || type == "single")
                {
                    colVal = colVal.Replace(",", ".");
                }
                string Query = String.Format("UPDATE t_sales SET " + colName + "='" + MySqlHelper.EscapeString(colVal) + "' WHERE sale_id=" + fieldCritValue + ";");
                mySqlCommand = new MySqlCommand(Query, mySqlConnection);
                int rowCount = mySqlCommand.ExecuteNonQuery();
                if (rowCount != 1)
                {
                    MessageBox.Show("Обновление на стороне сервера не произошло!");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
Не нравится только то, что приходится постоянно эксплуатировать схему данных из MySql . Но тут уж не знаю как выкрутиться. SHOW запросы на мускуле у пользователя могут быть запрещены. Можно закручивать в отдельную коллекцию типы данных полей ,которые соответствуют мускулу и гриду. Но не понравилось. Лучше точечно. Не надо следить за списками и массивами в классе.
1
785 / 616 / 273
Регистрация: 04.08.2015
Сообщений: 1,713
18.02.2020, 10:10
Цитата Сообщение от Сергей1980 Посмотреть сообщение
C#
1
2
//Строка для автоматического определения типа данных поля в таблице MySQL по имени текущей ячейки
String strSqlDefineType = "SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 't_sales' AND COLUMN_NAME = '" + colName + "'";
Можно ведь один раз получить схему таблицы, а не выполнять запросы каждый раз, когда пользователь редактирует ячейку. Всё, что вы пытаетесь изобрести, уже придумано. DataAdapter и CommandBuilder сделают всю работу за вас.
0
 Аватар для Сергей1980
547 / 377 / 16
Регистрация: 17.12.2009
Сообщений: 991
18.02.2020, 12:46  [ТС]
Igr_ok, давайте представим , что у меня один грид содержит 30 столбцов, другой 28. И я не хочу для каждого поля прописывать параметры вручную в commandbuilder. То есть не хочу описывать типа .add.Parametr() для каждого поля. А хочу просто накинуть один метод и чтобы завелась обработка сразу всех полей на гриде, в связке с правильным родным определением данных mysql. Как мне поможет commandbuilder? Никак. Если предлагаете решение , будьте добры показать ваш вариант) Пока есть один рабочий, и он мой )

Добавлено через 1 минуту
Ps. Надо ещё для обработки полей типа null сделать случай, сейчас попробую включить в код.
0
785 / 616 / 273
Регистрация: 04.08.2015
Сообщений: 1,713
18.02.2020, 13:08
Сергей1980, теория: https://dev.mysql.com/doc/dev/... uilder.htm
Для тех, кого пугает "много букв"
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static DataSet SelectRows(string myConnection, string mySelectQuery, string myTableName)
{
MySqlConnection myConn = new MySqlConnection(myConnection);
MySqlDataAdapter myDataAdapter = new MySqlDataAdapter();
myDataAdapter.SelectCommand = new MySqlCommand(mySelectQuery, myConn);
MySqlCommandBuilder cb = new MySqlCommandBuilder(myDataAdapter);
 
myConn.Open();
 
DataSet ds = new DataSet();
myDataAdapter.Fill(ds, myTableName);
 
//code to modify data in DataSet here
 
//Without the MySqlCommandBuilder this line would fail
myDataAdapter.Update(ds, myTableName);
 
myConn.Close();
 
return ds;}
Вам нужно изменить метод так, чтобы myDataAdapter можно было вызывать в других методах. И тогда для сохранения данных достаточно будет вызвать myDataAdapter.Update. И обновлять данные нужно не при завершении редактирования ячейки, а по завершении редактирования строки.
1
 Аватар для Сергей1980
547 / 377 / 16
Регистрация: 17.12.2009
Сообщений: 991
18.02.2020, 13:30  [ТС]
Цитата Сообщение от Igr_ok Посмотреть сообщение
И обновлять данные нужно не при завершении редактирования ячейки
С этим вопрос спорный, человека могут отвлечь, он может пойти налить кофе в столовую, и курсор останется на текущей строке , и данные так и не обновлены. В этот же момент другой человек может править другие поля в этой же строке. В общем то вопрос предпочтений. Я тоже раньше писал на событие потеря фокуса строки, либо текущая запись. Сейчас склоняюсь в сторону вставил->сразу изменилось. Даже если пользователь копипастом пробежится и изменит несколько десятков полей в столбце за 10-15 секунд, mysql от этого не умрет)

Цитата Сообщение от Igr_ok Посмотреть сообщение
//code to modify data in DataSet here
А как модифицировать код? Чтобы автоматически генерировать параметры для всех столбцов в гриде с разными типами данных, не привязываясь к перечислению их (столбцов) руками поштучно в коде?

Ваш пример в конце выдает датасет, но сама суть то не раскрыта)

Это знаете как,я могу примерно такой же накидать:

Java
1
2
3
4
5
6
private возвращаемыйТип СделатьКрасиво(){
//прам пам пам тут код
//пиу пиу и тут тоже
return переменнаяВозвращаемогоТипа;
 
}
0
785 / 616 / 273
Регистрация: 04.08.2015
Сообщений: 1,713
18.02.2020, 14:02
Цитата Сообщение от Сергей1980 Посмотреть сообщение
С этим вопрос спорный, человека могут отвлечь, он может пойти налить кофе в столовую, и курсор останется на текущей строке , и данные так и не обновлены. В этот же момент другой человек может править другие поля в этой же строке.
Microsoft о вас позаботился) При создании UpdateCommand используется оптимистическая блокировка.
Цитата Сообщение от Сергей1980 Посмотреть сообщение
А как модифицировать код?
Привязать ds к гриду. Пользователь вносит изменения в гриде, они передаются в источник данных(DataSet), myDataAdapter передает изменения в БД.
Цитата Сообщение от Сергей1980 Посмотреть сообщение
Чтобы автоматически генерировать параметры для всех столбцов в гриде с разными типами данных, не привязываясь к перечислению их (столбцов) руками поштучно в коде?
Я ведь писал, что DataAdapter и CommandBuilder сделают всё за вас. Главное - не мешать им)
Цитата Сообщение от Сергей1980 Посмотреть сообщение
Ваш пример в конце выдает датасет, но сама суть то не раскрыта)
Т.е. приведенный мною код нельзя скопировать/вставить в ваш проект? Это недостаток любой документации
0
 Аватар для Сергей1980
547 / 377 / 16
Регистрация: 17.12.2009
Сообщений: 991
18.02.2020, 14:21  [ТС]
Цитата Сообщение от Igr_ok Посмотреть сообщение
Я ведь писал, что DataAdapter и CommandBuilder сделают всё за вас. Главное - не мешать им)
То есть дополнительно не надо писать команду sql типа UPDATE и типы полей (нулевое,дабл,сингл, булевое итд myDataAdapter.Update съест по умолчанию?)
0
785 / 616 / 273
Регистрация: 04.08.2015
Сообщений: 1,713
18.02.2020, 14:43
Сергей1980, CommandBuilder формирует команды INSERT,UPDATE,DELETE для DataAdapter.
1
 Аватар для Сергей1980
547 / 377 / 16
Регистрация: 17.12.2009
Сообщений: 991
18.02.2020, 14:48  [ТС]
Я попробую обязательно вариант с CommandBuilder,спасибо , почитал, но пока не разобрался с параметризацией команд.
Это чем то напоминает prepared statement из других языков.

Параллельно доработал свой метод, с учетом обсчета нулевого значения поля:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                int colInd = dataGridView.CurrentCell.ColumnIndex; // индекс столбца текущей ячейки
                int rowInd = dataGridView.CurrentCell.RowIndex; // индекс строки текущей ячейки
                String colVal = Convert.ToString(dataGridView.CurrentCell.Value); //конвертация любого типа значения ячейки в текст
                String colName = dataGridView.Columns[colInd].Name; // имя текущей ячейки
                String fieldCritValue = dataGridView.Rows[e.RowIndex].Cells[0].Value.ToString(); // значение поля критерия выборки для Where
                //Строка для автоматического определения типа данных поля в таблице MySQL по имени текущей ячейки
                String strSqlDefineType = "SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 't_sales' AND COLUMN_NAME = '" + colName + "'";
                MySqlCommand mySqlCommand = new MySqlCommand(strSqlDefineType, DbConnection.mySqlConnection);
                MySqlDataReader reader = mySqlCommand.ExecuteReader();
                reader.Read();
                string type = reader.GetValue(0).ToString();// принимает тип поля из таблицы MySQL в текстовом виде
                reader.Close();
 
                // если значение текущей ячейки после изменения пустое 
                if (dataGridView.CurrentCell.Value == null || dataGridView.CurrentCell.Value.ToString().Trim().Equals(string.Empty))
                {
                    string Query = String.Format("UPDATE t_sales SET " + colName + "=NULL WHERE sale_id=" + fieldCritValue + ";");
                    mySqlCommand = new MySqlCommand(Query, mySqlConnection);
                }
                else
                //перечисляем варианты с учетом типов полей
                {
                    if (type == "date")
                    {
                        DateTime dateValue = DateTime.Parse(colVal);
                        colVal = dateValue.ToString("yyyy-MM-dd");
                    }
                    if (type == "double" || type == "single")
                    {
                        colVal = colVal.Replace(",", ".");
                    }
                    string Query = String.Format("UPDATE t_sales SET " + colName + "='" + MySqlHelper.EscapeString(colVal) + "' WHERE sale_id=" + fieldCritValue + ";");
                    mySqlCommand = new MySqlCommand(Query, mySqlConnection);
                    int rowCount = mySqlCommand.ExecuteNonQuery();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


Тоже достаточно просто, осталось вывести название таблиц и поле критерий выборки в отдельные переменные и можно пихать в отдельный класс)
0
 Аватар для Сергей1980
547 / 377 / 16
Регистрация: 17.12.2009
Сообщений: 991
19.02.2020, 00:28  [ТС]
Цитата Сообщение от Igr_ok Посмотреть сообщение
CommandBuilder формирует команды INSERT,UPDATE,DELETE для DataAdapter.
Огромное спасибо за помощь!

Разобрался насколько смог. Собрал тестовый вариант CRUD с билдером. Все работает супер:

Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public partial class f_products : Form
    {
 
        MySqlConnection mySqlConnection;
        MySqlDataAdapter mySqlDataAdapter;
        MySqlCommandBuilder mySqlCommandBuilder;
        DataTable dataTable;
        DataSet dataSet;
 
        public f_products()
        {
            InitializeComponent();
        }
 
        private void fill_products_Click(object sender, EventArgs e)
        {
            mySqlConnection = DbConnection.mySqlConnection;
            string query = "SELECT * FROM t_products";
            mySqlDataAdapter = new MySqlDataAdapter(query, mySqlConnection);
            mySqlCommandBuilder = new MySqlCommandBuilder(mySqlDataAdapter);
            mySqlDataAdapter.UpdateCommand = mySqlCommandBuilder.GetUpdateCommand();
            mySqlDataAdapter.DeleteCommand = mySqlCommandBuilder.GetDeleteCommand();
            mySqlDataAdapter.InsertCommand = mySqlCommandBuilder.GetInsertCommand();
            dataSet = new DataSet();
            mySqlDataAdapter.Fill(dataSet);
            dataTable = new DataTable();
            dataTable = dataSet.Tables[0];
            dataGridViewProducts.DataSource = dataTable;
        }
 
        private void btn_update_Click(object sender, EventArgs e)
        {
            mySqlDataAdapter.Update(dataSet);
        }
    }


C датасет пример классный, можно сразу обратится к структуре и данным всех объектов на мускуле. Супер. И связи между ними прокинуть.
0
 Аватар для Сергей1980
547 / 377 / 16
Регистрация: 17.12.2009
Сообщений: 991
19.02.2020, 16:00  [ТС]
Универсальным событием, определенным методом научного тыка можно использовать RowValidation.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.02.2020, 16:00
Помогаю со студенческими работами здесь

Описать класс домашняя библиотека, предусмотреть возможность работы с произвольным числом книг, поиск книги
Help please!!!))).Описать класс домашняя библиотека. Предусмотреть возможность работы с произвольным числом книг, поиск книги по...

Описать класс «домашняя библиотека». Предусмотреть возможность работы с произвольным числом книг, поиска книги
Друзья, не работает функция add. Программа крашится. Я понимаю, что он как бы пытается записать в то же место, но не знаю как, исправить....

Описать класс «домашняя библиотека». Предусмотреть возможность работы с произвольным числом книг, поиска книги по какому
Описать класс «домашняя библиотека». Предусмотреть возможность работы с произвольным числом книг, поиска книги по какому-либо признаку...

Библиотека для работы с БД
Здравствуйте. Порылся на форуме, вроде ничего подобного не нашёл, а именно: Мне необходимо разработать библиотеку (для использования...

Библиотека для работы с БД
Привет! Нужна нормальная библиотека под linux для подключения к базам данных, в особенности для Postgresql. Знаю у постгри есть своя...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru