Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/8: Рейтинг темы: голосов - 8, средняя оценка - 4.50
0 / 0 / 0
Регистрация: 10.02.2021
Сообщений: 14

Проблема с классом для работы с базой данных

21.10.2021, 18:57. Показов 1726. Ответов 6

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток!

Написал класс для работы с базой данных, но есть проблема - публичное поле Dataset'a. Я знаю, что так делать плохо. При использования метода Select приходится для выбора значения обращаться таким образом Database.ds.Tables[0].Rows[0][0].ToString(); — как решить данную проблему?

Если просто записывать в переменную значение, то вернется DataTable и его никак перебрать не получается. Может можно какой-нибудь метод написать для более правильного выполнения запроса и возврата данных?

Про ExecuteNonQuery тоже слышал, что лучше не юзать, но по другому не додумался - буду рад услышать любые замечания и улучшения. Код класса прилагаю ниже

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
class Database
    {
        private static readonly string ConnStr = @"Data Source=DESKTOP-Q8AEUVR\SQLEXPRESS; Initial Catalog = AgentsList; Integrated Security=true";
        public static DataSet ds;
        private static SqlDataAdapter sqlad;
        private static SqlCommand comnd;
 
        /// <summary>
        /// Метод, возвращающий результат выполнения запроса. Подходит только для SELECT
        /// </summary>
        /// <param name="QueryString">Строка запроса к БД</param>
        /// <param name="Params">Список параметров. По умолчанию пустой. Параметры в запросе нумеруются от 0 до n. 
        /// Для выполнения без параметров передается null</param>
        /// <returns>Строки данных записанные в экземпляр класса Dataset объект ds</returns>
        public static object Select(string QueryString, List<string> Params = null)
        {
            using (SqlConnection sqlconn = new SqlConnection(ConnStr))
            {
                sqlconn.Open();
                comnd = new SqlCommand(QueryString, sqlconn);
                sqlad = new SqlDataAdapter(QueryString, ConnStr);
                ds = new DataSet();
 
                if (!string.IsNullOrEmpty(QueryString) && !string.IsNullOrWhiteSpace(QueryString))
                {
                    if (Params != null)
                    {
                        for (int i = 0; i < Params.Count; i++)
                        {
                            comnd.Parameters.AddWithValue($@"@{i}", Params[i]);
                        }
 
                        sqlad.SelectCommand = comnd;
                        sqlad.SelectCommand.ExecuteNonQuery();
                    }
                    else
                    {
                        sqlad.SelectCommand = comnd;
                        sqlad.SelectCommand.ExecuteNonQuery();
                    }
                }
 
                sqlad.Fill(ds);
                sqlconn.Close();
 
                return ds.Tables[0];
            }
        }
 
        /// <summary>
        /// Метод выполнения хранимой процедуры
        /// </summary>
        /// <param name="ProcedureName">Имя хранимой процедуры</param>
        /// <param name="ProcedureParameters">Параметры для выполнения процедуры. Может быть пустым</param>
        public static void ExecuteProcedure(string ProcedureName, List<string> ProcedureParameters = null)
        {
            using (SqlConnection sqlconn = new SqlConnection(ConnStr))
            {
                sqlconn.Open();
 
                string PreBuiltQuery = $@"execute '{ProcedureName}' ";
                string BuiltQuery;
 
                if (!string.IsNullOrEmpty(ProcedureName))
                {
                    if (ProcedureParameters.Count > 0)
                    {
                        for (int i = 0; i < ProcedureParameters.Count; i++)
                        {
                            PreBuiltQuery += $@"@{i},";
                        }
 
                        BuiltQuery = PreBuiltQuery.Substring(0, PreBuiltQuery.Length - 1);
                    }
                    else
                    {
                        BuiltQuery = PreBuiltQuery;
                    }
 
                    comnd = new SqlCommand(BuiltQuery, sqlconn);
 
                    for (int i = 0; i < ProcedureParameters.Count; i++)
                    {
                        comnd.Parameters.AddWithValue($@"@{i}", ProcedureParameters[i]);
                    }
 
                    comnd.ExecuteNonQuery();
                    sqlconn.Close();
                }
                else
                {
                    throw new ArgumentException("Имя процедуры не может быть пустым!");
                }
            }
        }
 
        /// <summary>
        /// Метод вставки значений в таблицу
        /// </summary>
        /// <param name="TableName">Имя таблицы</param>
        /// <param name="FieldNames">Названия полей для вставки</param>
        /// <param name="FieldValues">Значения для полей</param>
        public static void Insert(string TableName, List<string> FieldNames, List<string> FieldValues)
        {
            using (SqlConnection sqlconn = new SqlConnection(ConnStr))
            {
                if (!string.IsNullOrEmpty(FieldNames.ToString()))
                {
                    if (!string.IsNullOrEmpty(FieldValues.ToString()))
                    {
                        if (FieldNames.Count.Equals(FieldValues.Count))
                        {
                            sqlconn.Open();
 
                            string PreBuiltQuery = $@"insert into {TableName}(";
                            string BuiltQuery;
 
                            foreach (string fn in FieldNames)
                            {
                                PreBuildedQuery += fn + ",";
                            }
 
                            PreBuiltQuery = PreBuiltQuery.Substring(0, PreBuiltQuery.Length - 1);
                            PreBuiltQuery += ") values (";
 
                            for (int i = 0; i < FieldValues.Count; i++)
                            {
                                PreBuiltQuery += $@"@{i},";
                            }
 
                            BuiltQuery = PreBuiltQuery.Substring(0, PreBuiltQuery.Length - 1);
                            BuiltQuery += ")";
 
                            comnd = new SqlCommand(BuiltQuery, sqlconn);
 
                            for (int i = 0; i < FieldValues.Count; i++)
                            {
                                comnd.Parameters.AddWithValue($@"@{i}", FieldValues[i]);
                            }
 
                            comnd.ExecuteNonQuery();
                            sqlconn.Close();
                        }
                        else
                        {
                            throw new Exception("Количество элементов в списке Имен полей и в списке Значений должно быть одинаковым");
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Список с значениями полей не может быть null или содержать 0 значений");
                    }
                } 
                else
                {
                    throw new ArgumentException("Список с именами полей не может быть null или содержать 0 значений");
                }
            }
        }
 
        /// <summary>
        /// Метод обновления записей в таблице
        /// </summary>
        /// <param name="TableName">Имя таблицы</param>
        /// <param name="Setter">Поле, значение которого необходимо обновить</param>
        /// <param name="Value">Значение, которое необходимо присвоить</param>
        /// <param name="Condition">Условие по которому значение присваивается конкретному полю</param>
        public static void Update(string TableName, string Setter, string Value, string Condition = "ID = 1")
        {
            using (SqlConnection sqlconn = new SqlConnection(ConnStr))
            {
                if (!string.IsNullOrEmpty(TableName))
                {
                    if (!string.IsNullOrEmpty(Setter))
                    {
                        if (!string.IsNullOrEmpty(Value))
                        {
                            sqlconn.Open();
                            string Query = $@"update {TableName} set {Setter} = '{Value}' where {Condition}";
                            comnd = new SqlCommand(Query, sqlconn);
                            comnd.ExecuteNonQuery();
                            sqlconn.Close();
                        }
                        else
                        {
                            throw new ArgumentException("Значение не может быть пустым!");
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Сеттер не может быть пустым!");
                    }
                }
                else
                {
                    throw new ArgumentException("Имя таблицы не может быть пустым!");
                }
            }
        }
    }
Добавлено через 10 минут
В методе Insert() опечатка c PreBuildedQuery - редактировал недавно файл и не везде возможно заменил, уже исправил
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.10.2021, 18:57
Ответы с готовыми решениями:

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

Программа для работы с базой данных
Нужно написать программу на Delphi, которая будет работать с базой данных (100 000 записей, формат базы не важен), и должна осуществлять...

Программа для работы с базой данных
Ya doljen v ocheni kratkii sroc zdelati v visual c++ programu dlea raboty sa bzami danih, no ya v atom nicego ne mysliu, esli u cavoto esti...

6
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
21.10.2021, 19:26
Все, что Вы понаписывали, в печку !
Работа с СУБД заключается в двух "ипостясях" - модели, отражающие сущности, хранящиеся в Базе данных (таблицы или результаты выборки) и контексте/репозитории, содержащем (инкапсулирующем) методы для обмена данными с БД.
Первые используются для манипулирования информацией (например - отображения), вторые - для получения моделей или внесения через эти самые модели изменений в таблицы БД.

Сами модели у Вас просто отсутствуют, вместо них в методах класса, названного Вами "как с бодуна" Database, упоминаются какие-то мутные конструкции, претендующие на какую-то "универсальность". Весь этот жуткий коктейль должен якобы работать непонятно с чем и непонятно как.

Опять же использование адаптеров и тэйблов без всякого понятия а что это такое и для чего они, собственно, нужны. И те, и другие используются в самом клиентском коде, связанным с интерфейсом и никого прямого отношения в БД не имеют. Зачем пихать их в класс БД, который по идее должен быть совершенно независим от интерфейса ?
0
0 / 0 / 0
Регистрация: 10.02.2021
Сообщений: 14
21.10.2021, 19:29  [ТС]
Ну то есть хотите сказать, что в классе для работы бд не должно быть никаких адаптеров и команд, а построено должно быть все чисто на абстракциях? Ну про модели я знаю, но пока не разбирался подробнее как с ними в сишарпе работать. Как в шараге научили, то я и написал, улучшив в пару раз
0
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
21.10.2021, 19:40
Цитата Сообщение от sometimes_ago Посмотреть сообщение
Ну то есть хотите сказать, что в классе для работы бд не должно быть никаких адаптеров и команд, а построено должно быть все чисто на абстракциях?
Я не знаю о каком классе "для работы с БД" Вы говорите.
Если это некий класс, который умеет работать с произвольными, неизвестными заранее базами данных, то Ваша задумка - фикция, утопия.
Если же Вы имеете в виду конкретную БД, то для работы с ней, повторюсь, нужны : а) модели, б) имплементация.
Первые - абстрактные, вторые - вполне себе конкретные, но работающие с абстрактными моделями.

Добавлено через 5 минут
Вы путаете адаптер (xxxAdapter) с командами (xxxCommand).
Очевидно, Вас ввели в заблуждение "уроки", которые Вы, не поняв сути, просто скоммуниздили в свой проект, не потрудившись прочитать что это за классы и для чего они используются.
xxxCommand безусловно используется в имплементации, xxxAdapter - безусловно нет. Неужели Вам надо объяснять почему ?
0
0 / 0 / 0
Регистрация: 10.02.2021
Сообщений: 14
21.10.2021, 19:41  [ТС]
Понял. Большое Вам спасибо. Буду разбираться с моделями и имплементациями, может и получится что-то дельное
Миниатюры
Проблема с классом для работы с базой данных  
0
0 / 0 / 0
Регистрация: 10.02.2021
Сообщений: 14
21.10.2021, 19:46  [ТС]
Ну и от того что я прочитаю про данные классы - научусь ли я ими пользоваться уже другой вопрос
Так что можете объяснить, пожалуйста, если хотите
0
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
21.10.2021, 19:58
Лучший ответ Сообщение было отмечено sometimes_ago как решение

Решение

Грубо говоря, есть два способа организации приложения для работы с базами данных
1. "Ручной"
Никаких классов, никаких абстракций. Все пишется в коде обработчиков событий формы.
Данные читаются из БД и суются в тэйбл и адаптер, который привязывается к гриду.
На выходе имеем грид, который редактируем и внесенные изменения заносятся в таблицу БД.

Приложение даже может работать. Для курсача или лабы вполне сойдет. Для реального проекта, особенно для работы в многопользовательском режиме - сплошные грабли с колдобинами - кол придется мощно править - увеличив его в итоге примерно втрое-впятеро.
2. "Правильный"
Приложение ничего не знает ни о какой "базе", "таблицах" и прочих пирогов с капустой. Оно работает с абстракциями (моделями), которые может отображать где-то (грид, листвью, комбобокс и т.д.) и которыми обменивается через методы некоего класса (репозитория, контекста). Для получения списка моделей (например для грида) используется один метод, для получения одной модели (как правило, по id) - другой, для передачи измененной модели для внесения в БД - третий, для добавления новой модели - четвертый и т.д.
Класс репозитория (контекста) ничего не знает ни о каких графических элементах и вообще ничего, что делается с извлеченными им данными в формах приложения. В его обязанность входит получение от сервера и передача этих данных программе или получение их от программы для внесения изменений в таблицы БД на сервере.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
21.10.2021, 19:58
Помогаю со студенческими работами здесь

Приложение для работы с базой данных
Всем доброго времени суток!!! У меня есть приложение для работы с БД SQL Server. Оно будет работать на другой машине, если не...

Класс для работы с базой данных
Подскажите, пожалуйста, гарантирует ли данный класс закрытие connection по завершению работы с ним ? И выскажите свое мнение по поводу...

Приложение для работы с базой данных
У меня есть приложение суть такая есть база данных в ней таблица, в приложении присутствуют фильтры по столбцам &quot;data&quot; и...

Приложение для работы с базой данных
Здравствуйте. Надо было с ноля спроектировать и создать базу данных, затем заполнить данными. Данные заполнял в Маикрософт ЭСКУЭЛЬ...

Класс для работы с базой данных
Здравствуйте, Нашел сайт с классом для работы с базой данных: &lt;?php class DataBase { private static $db = null; //...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
1С: Контроль уникальности заводского номера
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере документа выдачи шин для спецтехники с табличной частью. Данные берутся из регистра сведений, по которому настроено. . .
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
1С: Программный отбор элементов справочника по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор по наименованию группы. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит значение перечислений. / / Событие "НачалоВыбора" реквизита на форме. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru