С наступающим Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы
C#: Базы данных, ADO.NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
Graf1385
0 / 0 / 5
Регистрация: 09.10.2015
Сообщений: 184
1

Как правильно передать данные из таблицы DataGridView в SQL базу данных

24.06.2017, 19:47. Просмотров 884. Ответов 14
Метки нет (Все метки)

Здравствуйте. Есть таблица DataGridView которая содержит данный которые добавляет пользователь или загружает из файла. Как мне правильно передать эти данные в базу данных, находящиеся на удалённом сервере с минимальными затратами ресурсов компьютера и сервера? Понятно что можно создать цикл в котором будет передаваться все данные с помощью запросов построчно, но вот правильно ли это?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.06.2017, 19:47
Ответы с готовыми решениями:

Как программно вывести данные из таблицы базы ms sql на форму в dataGridView
Ребят, подскажите как программно вывести данные из таблицы базы ms sql на форму...

Как с помощью MonthCalendar вывести в DataGridView с sql таблицы данные с определенной датой?
Всем доброго времени суток! Подскажите пожалуйста как с помощью MonthCalendar...

Как правильно создавать таблицы SQL База Данных
Приветствую. Вот какая у меня проблема необходимо программно создавать ...

Сохранение данных из datagridview в базу данных под MS sql server 2012
Доброго времени суток. Делаю курсовую, и до этого момента думал, что самое...

Из dataGridView в базу данных MS SQL: строки переносятся не по порядку
Есть заполненный dataGridView (21497 строк). Есть таблица в базе данных с...

14
hoolygan
352 / 279 / 76
Регистрация: 21.06.2016
Сообщений: 1,101
24.06.2017, 21:44 2
Начнем с того, что DataGridView это контрол, а не таблица. Таблица - это DataTable. По поводу передпчи - я бы советовал написать DAL небольшой, и передавать на сервер не весь пакет, а только то, что отдает метод GetChanges().
0
Graf1385
0 / 0 / 5
Регистрация: 09.10.2015
Сообщений: 184
24.06.2017, 23:11  [ТС] 3
Понятно что контрол, но пользователю всё ровно контрол это или таблица он видит перед собой таблицу с данными, которую ему необходимо передать БД. Вопрос в том как лучше передать мне данные, DAL это само собой, его писать в любом случаи как бы я данные не передавал.
0
Igr_ok
389 / 366 / 179
Регистрация: 04.08.2015
Сообщений: 1,006
25.06.2017, 09:05 4
Graf1385, есть несколько вариантов.
1. Формирование динамического запроса, в котором будет набор команд. Например:
SQL
1
2
3
4
INSERT INTO table1(Field1,Field2) VALUES(value1,value2);
INSERT INTO table1(Field1,Field2) VALUES(value3,value4);
...
INSERT INTO table1(Field1,Field2) VALUES(valueN,valueK);
Но это для исключительных случаев, т.к. формирование динамического запроса-тот еще гемор.
2. Использование специальных классов для массовой вставки. Например, SQlBulkCopy для MS SQL. Это лучший вариант.
3. Импорт данных из файла. Пример для MS SQL: https://docs.microsoft.com/en-us/sql...t-transact-sql

Для случаев, когда нужно предварительно проанализировать импортируемые данные(например, данные могут содержать уже существующий первичный ключ и тогда вместо insert нужен update), создается временная(в том смысле, что данные в ней хранятся временно, и перед очередным импортом очищаются) таблица и импорт делается в нее. Далее к ней применяются команды SQL, например
C#
1
2
isert into table1
select * from tmpTable where Field1 not in(select field1 from table1)
0
hoolygan
352 / 279 / 76
Регистрация: 21.06.2016
Сообщений: 1,101
25.06.2017, 10:01 5
Graf1385, судя по 1-му вопросу непонятно. Вы же не со стороны пользователя спрашиваете, а со стороны разработчика. Поэтому вопрос о цикле - это даже не смешно было. Представим, что в таблице перед пользователем 500-800 строк по 10 столбиков, половина из них интовые поля, а половина строковые. Также представим, что пользователь изменил данные в 3-х строках и хочет сохранить, и сравним разные варианты. Цикл построчно даже не рассматриваем, как вообще не заслуживающий внимания.
1. Использования bulkcopy - ерунда, потому что перед заливкой нужно очищать таблицу (это при условии, что таблица в приложении это выборка только с 1-ой таблицы в сиквеле)
2. Из файла - та же фигня, что и с первым вариантом, только еще процесс записи/чтения занимает время
3. Передача всей таблицы из шарпа в сиквел. В зависимости от количества строк может быть и 2 мб и 20 мб информации. Когда собрали и передали, нужно еще и анализировать на стороне сиквела на момент insert/delete/update.
3. Использование GetChanges() - передаются только те строчки на сиквел, которые поменялись, к тому же каждая строка имеет признак, что с ней происходило, добавилась она, удалилась или изменилась. Сиквелу даже не придется анализ делать, а медод этот шарповый отработает за доли секунды даже при 100 000 строк шарпа.
Как итог, вместо передачи по сети иногда десятков мегабайт трафа и анализа таблиц - достаточно передать десяток килобайт с тем же успехом.
Как то вот так.
0
Igr_ok
389 / 366 / 179
Регистрация: 04.08.2015
Сообщений: 1,006
25.06.2017, 10:50 6
hoolygan, в 1-м посте написано
Цитата Сообщение от Graf1385 Посмотреть сообщение
Есть таблица DataGridView которая содержит данный которые добавляет пользователь или загружает из файла
GetChanges() здесь не поможет, т.к. при чтении из файла состояние у всех строк будет одинаковое.
Для варианта, если пользователь ручками набивает данные в грид, а потом их нужно перенести в таблицу, аналогично. Все записи новые. Но тут всё просто, можно использовать DataAdapter.
0
Graf1385
0 / 0 / 5
Регистрация: 09.10.2015
Сообщений: 184
25.06.2017, 16:06  [ТС] 7
Давайте так вот пример метода который может передать 4 массива c одинаковым количеством значений в БД. Я впервые сталкиваюсь с SQL, но понимаю что это не правильно. Вот скажите мне как правильно передать эти 4 массива ну или таблицу.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public void Test(Guid par1, Guid par2, List<long> array1, long par3,  List<string> array2, List<string> array3, List<string> array4, string par4, DateTime par5, string par6)
        {
            try
            {
                using (SqlConnection connect = new SqlConnection(Settings.Default.StringConnect))
                {
                    connect.Open();
                    SqlCommand command;
                    for (int i = 0; i < nameOfEquipment.Count; i++)
                    {      
                        queriesString = String.Format(@"EXEC [dbo].[Test] @iD = '{0}', @MainStockID = '{1}', @StockID = '{2}', @NomenclatureNumber = '{3}', @FactoryNmber = '{4}', @NameOfEquipment = '{5}'," +
                            "@Unit = '{6}', @Amountst = '{7}', @Coming = '{8}', @DateOfLastMove = '{9}', @StatusMove = '{10}'", Guid.NewGuid(), par1, par2, array1, par3, array2, array3, array4, par4, par5, par6);
                        command = new SqlCommand(queriesString, connect);
                        command.ExecuteNonQuery();
                    }                     
                }
            }
            catch (Exception ex)
            {
               
            }
        }
0
hoolygan
352 / 279 / 76
Регистрация: 21.06.2016
Сообщений: 1,101
25.06.2017, 16:47 8
Graf1385, Вы так и не сказали, какая субд используется. Если это ms sql - то все можно решить намного более приятным и читабельным кодом.
Суть его вот в чем. Создаете отдельный класс-модель, в котором будут все открытые поля-данные, будь то массивы, таблицы, строки, все, что нужно по ТЗ. Далее, когда нужно отправить в сторону сиквела - то сериализуете его в xml, и передаете 1-им параметром, без всякого гавнокода типа циклов. Циклы для связи с сервером - это самое последнее, что можно использовать, так как может возникнуть проблема разрыва связи, и отловить, что уже передалось, а что нет будет ну очень тяжело.
Дальше есть еще 1 проблема, с ней столкнетесь попозже, когда будете оптимизировать приложение. При запуске процедуры очень долго идет процесс компиляции и построения плана выполнения, а клиент захочет постоянно бросать новые порции запуска. Таким образом будет висеть всё и вся. Незаметно при 10 итерациях и таблице в сиквеле в 20 значений (а складывается чувство, что новички считают, что большие объемы никогда никто не держит). Но уже при 100 000 записей, когда идет update и лочится таблица, а еще днсятки или сотни человек ждут от нее данные - то тут бока и вылазят. И начинаются висяки при простых казалось бы операциях.
Поэтому циклы использовать не просто нежелательно - а капец как по рукам давать нужно за такое. Имею в виду тот цикл, что у Вас в примере.
Но есть и другой пример, когда нужно на сервер отправлять миллионы строк, и их распределять на разные таблицы. Тогда уже лучше разбивать на несколько частей в цикле, закидывать их в псевдовременную таблицу, и потом использовать ее для заливки по целевым таблицам. Но это уже индивидуально нужно каждую задачу решать.
Но все это касается многопользовательских нагруженных систем. Если используете на 1 пользователя, и у Вас 5 строчек - то о таких вещах не задумываются, к сожалению. А стоило бы
1
Graf1385
0 / 0 / 5
Регистрация: 09.10.2015
Сообщений: 184
25.06.2017, 21:08  [ТС] 9
База My Sql. Так смысл я понял сериализую класс с нужными мне полями и передаю его в сервер. Теперь у меня ещё больше вопросов. Процедура я так понимаю должна принимать xml тип данных. А как процедура дисериализует эту структуру объясните пожалуйста желательно с примером кода.
0
hoolygan
352 / 279 / 76
Регистрация: 21.06.2016
Сообщений: 1,101
25.06.2017, 21:21 10
Graf1385, нет, никак.... Мы тут все советы давали по ms sql
Вот так. Вся переписка..... хм с my sql у меня не очень много опыта, к сожалению. Но точно, что xml он не понимает.
1
Graf1385
0 / 0 / 5
Регистрация: 09.10.2015
Сообщений: 184
25.06.2017, 21:33  [ТС] 11
Так погодите получается что и принимать данные с сервера тоже лучше в XML а потом десериализовать его в программе?

Добавлено через 5 минут
Всё правильно вы давали это я ошибся ms sql
0
hoolygan
352 / 279 / 76
Регистрация: 21.06.2016
Сообщений: 1,101
25.06.2017, 21:58 12
Лучший ответ Сообщение было отмечено Graf1385 как решение

Решение

Graf1385, нет, хуже. Лучше использовать биндинг. А вообще идеально - это использование MVC шаблона, и биндинг в моделе. Далее контроллером связываете модель с контролами во вьюшке. А вот передачу на сиквел - да, красивее всего в xml формате. Сиквел его читает довольно быстро. Но все сильно зависит от задачи. Строить mvc на одноразовую загрузку пары файлов глупо. А вот при средней сложности системах - это самое оно.
1
Graf1385
0 / 0 / 5
Регистрация: 09.10.2015
Сообщений: 184
25.06.2017, 22:36  [ТС] 13
Это вообще новые слова MVC, биндинг ладно разберёмся с этими животными. Но всё таки как мне дисериализовать XML документ на сервере?
0
hoolygan
352 / 279 / 76
Регистрация: 21.06.2016
Сообщений: 1,101
26.06.2017, 09:15 14
Лучший ответ Сообщение было отмечено Graf1385 как решение

Решение

Это не сложно, вот, например, кусок нашей процедурки
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE PROCEDURE [dbo].[bla-bla-bla]
    @data varchar(max) = NULL
AS
BEGIN TRY
DECLARE @dataXML xml = @data
  SELECT
    x.value('businessId[1]', 'tinyint') AS businessId, 
    x.value('number[1]', 'int') AS number, 
    x.value('lagerId[1]', 'int') AS lagerId 
   
  INTO #QuickInputLagers
  FROM @dataXML.nodes('//DocumentElement/Data') t(x)
  JOIN #Businesses b ON b.businessId = x.value('businessId[1]', 'tinyint')
....
END
Вот тут мы закинули в темповую табличку #QuickInputLagers все лагера, что совпадают по определенному businessId.
Далее делаем с этой табличкой все, что хотим. Иди вот другой пример
T-SQL
1
2
3
4
5
6
7
8
9
10
11
;WITH XMLNAMESPACES ('urn:schemas-microsoft-com:xml-diffgram-v1' AS diffgr)
  UPDATE t
    SET
      t.partition = x.value('partition [1]', 'int'), 
      t.MinCount = x.value('MinCount[1]', 'int'), 
      t.BreakTime = x.value('BreakTime[1]', 'datetimeoffset'), 
      t.WFilials = x.value('WFilials[1]', 'varchar(max)') 
    FROM Tray t
    INNER JOIN @xmlData.nodes('//DocumentElement/GlobalSettings') t(x) 
            ON x.value('businessId[1]', 'int') = t.businessId
    WHERE x.value('@diffgr:hasChanges', 'varchar(255)') = 'modified'
Тут даже лучше видно, что происходит - идет выборка только тех значений, которые изменились в приложении.
Как-то так.
1
Graf1385
0 / 0 / 5
Регистрация: 09.10.2015
Сообщений: 184
26.06.2017, 10:52  [ТС] 15
Спасибо.
0
26.06.2017, 10:52
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.06.2017, 10:52

Запись данных в базу данных SQL и выгрузка таблицы в форму
Нужно сделать 2 формы, одну с несколькими textBox'ами, чтобы при нажатии кнопки...

Как правильно построить запрос и передать его в datagridview?
Здравствуйте, занимаюсь написанием Нейлоровской диагностирующей системы. Логику...

Не получается обновить данные в БД SQL Server при изменении данных в dataGridView
ADO.NET C# Добавлено через 2 минуты using System; using...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru