Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.85/41: Рейтинг темы: голосов - 41, средняя оценка - 4.85
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
MS SQL

ID связанных таблиц 2

17.05.2020, 11:06. Показов 8890. Ответов 88
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток, нужен совет(подсказка, пример) по следующей задаче:
Имеются в БД(MSSQL) две таблицы, головная "Покупки" и дополнительная "ПокупкаИнфо".
У первой есть первичный уникальный ключ, по полю ID(со свойством IDENTITY).
У второй таблицы есть составной "PRIMARY KEY(ПокупкаID,LineItem)".

Получается связка такая, на каждый уникальный "Покупки.ID" приходится по нескольку "ПокупкаИнфо.ПокупкаID".
С "Покупки.ID" автоматически(в SQL) создаётся новый номер.
А вот с "ПокупкаИнфо.ПокупкаID" возникает вопрос:
Как в С# сделать так , что бы для "ПокупкаИнфо.ПокупкаID" присваивался тот же номер что и у "Покупки.ID" ?

Эта же тема была тут: ID связанных таблиц
Но там сказали пойти сюда)
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.05.2020, 11:06
Ответы с готовыми решениями:

Сохранение связанных таблиц
Доброго времени суток! Проблема заключается в том что у меня есть три таблицы в БД, Специальность->Группа->Абитуриент...

Отображение связанных таблиц
Здравствуйте Не подскажите как такое можно реализовать? Есть 2 таблицы на форме. Они связаны 2 ключом. Получается, выделяешь строку в...

Работа с Id из связанных таблиц
Всем доброго времени суток!!! Работаю на языке с# c средой разработки баз данных ms sql server Вывел с базы данных информацию одной из...

88
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
07.10.2020, 16:11  [ТС]
Студворк — интернет-сервис помощи студентам
У меня вот на этом месте:
C#
1
2
3
4
var orderId = conn.QueryFirst<int>($@"INSERT INTO Покупки ([ПоставщикID], [PrihodDate]) VALUES (@ПоставщикID, @PrihodDate);SELECT SCOPE_IDENTITY()",
 
                         // можем использовать анонимные типы 
                         new { ПоставщикID = 100500, PrihodDate = DateTime.Now }); // вот тут
Получается конфликт с ключом:
Необработанное исключение типа "System.Data.SqlClient.SqlException" в System.Data.dll

Дополнительные сведения: Конфликт инструкции INSERT с ограничением FOREIGN KEY "FK__Покупки__Поставщ__22AA2996". Конфликт произошел в базе данных "Base5", таблица "dbo.Поставщики", column 'ID'.

Выполнение данной инструкции было прервано.

А вот так , целиком выглядит моя чудо-кнопочка:
Кликните здесь для просмотра всего текста
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
   class OrderItem
        {
            public int покупкаID { get; set; }
 
            public int LineItem { get; set; }
 
            public int ProductID { get; set; }
 
            public int Qty { get; set; }
 
            public int Price { get; set; }
        }
        private void button3_Click(object sender, EventArgs e)
        {
            int ПоставщикID = int.Parse(label22.Text);
            DateTime PrihodDate = Convert.ToDateTime(dateTimePicker1.Text);
            //int покупкаID = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["покупкаIDDataGridViewTextBoxColumn"].Value.ToString());
            int LineItem = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["LineItemDataGridViewTextBoxColumn"].Value.ToString());
            int ProductID = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["ProductIDDataGridViewTextBoxColumn"].Value.ToString());
            int Qty = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["QtyDataGridViewTextBoxColumn"].Value.ToString());
            int Price = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["PriceDataGridViewTextBoxColumn"].Value.ToString());
 
            using (var conn = new SqlConnection(@"Data Source=IGOR-PC\SQL150916;Initial Catalog=Base5;Integrated Security=True"))
                 {
                     using (var tran = new TransactionScope())
                {
                    
 
 
 
                 
                    // Вносим покупку
                    var orderId = conn.QueryFirst<int>($@"INSERT INTO Покупки ([ПоставщикID], [PrihodDate]) VALUES (@ПоставщикID, @PrihodDate);SELECT SCOPE_IDENTITY()",
 
                         // можем использовать анонимные типы 
                         new { ПоставщикID = 100500, PrihodDate = DateTime.Now });
 
                         // Откуда-то получаем список товара
                         // В данном случае заполняем руками
                         // Каждой позиции выставляем ранее полученный orderId
                         var orderItems = new[]
                         {
                         new OrderItem { покупкаID = orderId, LineItem = 1, ProductID = 2, Qty = 3, Price = 4 },
                         new OrderItem { покупкаID = orderId, LineItem = 2, ProductID = 3, Qty = 4, Price = 5 }
                         };
 
                         // Вносим товар
                         // Dapper сам догадается, что команду нужно повторить N раз,
                         // когда увидит, что в параметрах коллекция
                         conn.Execute($@"INSERT INTO ПокупкиИнфо(ПокупкаID, LineItem, ProductID, Qty, Price)VALUES(@ПокупкаID, @LineItem, @ProductID, @Qty, @Price)", orderItems);
 
 
                         tran.Complete();
                     this.покупкиTableAdapter1.Fill(this.base5DataSet13.Покупки);
                     this.tabControl1.SelectedTab = tabPage1;
                 }
                }
}
0
Эксперт .NET
 Аватар для Usaga
14790 / 9564 / 1367
Регистрация: 21.01.2016
Сообщений: 36,060
07.10.2020, 16:18
7-2-3, мне показалось очевидным не заострять внимание на том факте, что я вставляю данные от балды и что вы свои РЕАЛЬНЫЕ данные подставить должны...

А ещё, чтобы не писать вот такую уродливую портянку:

Кликните здесь для просмотра всего текста

C#
1
2
3
4
            int LineItem = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["LineItemDataGridViewTextBoxColumn"].Value.ToString());
            int ProductID = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["ProductIDDataGridViewTextBoxColumn"].Value.ToString());
            int Qty = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["QtyDataGridViewTextBoxColumn"].Value.ToString());
            int Price = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["PriceDataGridViewTextBoxColumn"].Value.ToString());


Можно в свойство DataGridView.DataSource затолкать коллекцию любого класса, а потом получить ссылку на выбранный экземпляр и уже его передать в запрос. Это в 100500 раз удобнее, чем руками по яйчейкам бегать. Да у текстбокса есть средства байндинга данных. Но это я вам уже не буду показывать-рассказывать. Терпения мне не хватит. Сами почитайте. И не говорите мне, что сейчас на это времени нет. Руками по контролам бегать существенно дольше, чем один раз разобраться и уже КАЖДЫЙ РАЗ писать куда более компактный и качественный код. Это как с Dapper'ом.
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
07.10.2020, 18:04  [ТС]
Я немного подправил, теперь получается одна строка проскакивает, а если вторую ставить застревает:

Необработанное исключение типа "System.Data.SqlClient.SqlException" в System.Data.dll

Дополнительные сведения: Нарушено "PK__ПокупкаИ__EDF010DFC00E088D" ограничения PRIMARY KEY. Не удается вставить повторяющийся ключ в объект "dbo.ПокупкаИнфо". Повторяющееся значение ключа: (126, 2).
0
Эксперт .NET
 Аватар для Usaga
14790 / 9564 / 1367
Регистрация: 21.01.2016
Сообщений: 36,060
07.10.2020, 18:31
7-2-3, текст ошибки вполне себе говорящий. Вы руками в "ПокупкаИнфо" ID вставляете? Зачем? Думаете база хуже это сделает?
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
07.10.2020, 18:39  [ТС]
Нет, он автоматически вставляется если строка одна.
А вторую почему то не хочет брать.
0
Эксперт .NET
 Аватар для Usaga
14790 / 9564 / 1367
Регистрация: 21.01.2016
Сообщений: 36,060
07.10.2020, 18:44
Цитата Сообщение от 7-2-3 Посмотреть сообщение
А вторую почему то не хочет брать.
Ну наверное потому, что вы сами ID вставляете. Первая вставляется потому, что ID пока ещё уникальный. А вторая строка отвергается, потому, что такой ID уже есть. Вот и "вставляется автоматически".
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
07.10.2020, 18:49  [ТС]
Ну она же вот отсюда берётся:
C#
1
var orderId = conn.QueryFirst<int>($@"INSERT INTO Покупки ([ПоставщикID], [PrihodDate]) VALUES (@ПоставщикID, @PrihodDate);SELECT SCOPE_IDENTITY()",
А потом вот сюда вставляется:
C#
1
2
3
 var orderItems = new[]
                         {
                         new OrderItem { покупкаID = orderId,
так ?

Я бы сюда весь код прилепил, но подумал что лучше не надо)
0
Эксперт .NET
 Аватар для Usaga
14790 / 9564 / 1367
Регистрация: 21.01.2016
Сообщений: 36,060
07.10.2020, 18:52
Цитата Сообщение от 7-2-3 Посмотреть сообщение
Ну она же вот отсюда берётся:
Отсюда берётся значение первичного ключа (ID) новой записи из таблицы Покупки.

Цитата Сообщение от 7-2-3 Посмотреть сообщение
А потом вот сюда вставляется:
А сюда оно должно идти как значение ВНЕШНЕГО ключа. Ссылка на "Покупку". А в базе это поле у вас, очевидно, является первичным ключом. Вот вы и получаете что получаете. Разберитесь, что и куда вы хотите вставить. Это уже не вопрос этой темы. Это вам уже самому надо разобраться что вы в базе наворотили и как вы сами с этим работаете.
1
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
07.10.2020, 19:34  [ТС]
Первичный ключ убрал.
И конечно из-за вот этого безобразия:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
int LineItem = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["LineItemDataGridViewTextBoxColumn"].Value.ToString());
            int ProductID = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["ProductIDDataGridViewTextBoxColumn"].Value.ToString());
            int Qty = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["QtyDataGridViewTextBoxColumn"].Value.ToString());
            int Price = int.Parse(dataGridView4.Rows[dataGridView4.CurrentCell.RowIndex].Cells["PriceDataGridViewTextBoxColumn"].Value.ToString());


Получаю вот такие строки:
Изображения
 
0
Эксперт .NET
 Аватар для Usaga
14790 / 9564 / 1367
Регистрация: 21.01.2016
Сообщений: 36,060
07.10.2020, 19:55
Цитата Сообщение от 7-2-3 Посмотреть сообщение
Получаю вот такие строки:
Всё верно. Вы одну и ту же строку вставляете несколько раз)
0
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
07.10.2020, 22:08
Usaga, вот зря Вы учите человека плохому

Мало того, что Ваш способ "копить" данные, чтобы затем "заскопить" их кучей в базу, никак не влазит в веб, так он еще и ущербен на WF - представьте себе, вот вводит какая-нибудь Маруся накладную в 20 строк, ввела уже 19 и долбит последнюю,- и тут - БАЦ и вырубается лепездричесвто ! Ну и все пропало
0
Эксперт .NET
 Аватар для Usaga
14790 / 9564 / 1367
Регистрация: 21.01.2016
Сообщений: 36,060
08.10.2020, 03:19
MsGuns, что, простите?
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
08.10.2020, 08:59  [ТС]
Имеется введу, что её 19 набитых строк пропадут даром.
Но мне пока не до проблем Маруси, мне бы главное чтоб моя программуличка хоть как-нибудь заработала)
0
Эксперт .NET
 Аватар для Usaga
14790 / 9564 / 1367
Регистрация: 21.01.2016
Сообщений: 36,060
08.10.2020, 10:03
7-2-3, вообще, то что он имел в виду к данному вопросу особо и не относится. Можно хоть всё скопом сохранять, хоть строки по очереди, по мере их ввода. Это уже другой вопрос, затрагивающий конкретные требования к целости и непротиворечивости данных.

Вы уже заставили своё приложение сохранять нормально?
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
08.10.2020, 15:09  [ТС]
Хех, пока нет.
Пытаюсь найти информацию, как это правильно реализовать.
0
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
08.10.2020, 17:02
Цитата Сообщение от Usaga Посмотреть сообщение
MsGuns, что, простите?
Что именно Вам не ясно ?
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
08.10.2020, 19:32  [ТС]
"В первом(запросе) вы вносите запись в "Покупки" и получаете ID. Второй собираете в цикле в один пакет (одна строка SQL-запроса) и отправляете в базу"

Получается мне ещё там цикл нужен ?
Возможно foreach
0
Эксперт .NET
 Аватар для Usaga
14790 / 9564 / 1367
Регистрация: 21.01.2016
Сообщений: 36,060
12.10.2020, 17:16
Цитата Сообщение от MsGuns Посмотреть сообщение
Что именно Вам не ясно ?
Что не так в том, что я советовал? Откуда вырисовывались вещи, которые даже близко не поднимаются в вопросе ТСа?

Цитата Сообщение от 7-2-3 Посмотреть сообщение
Получается мне ещё там цикл нужен ?
Возможно foreach
В случае с Dapper никаких циклов не нужно. В случае, когда вы решили запрос руками собрать... Сами как думаете?)
0
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
12.10.2020, 18:51

Не по теме:

Цитата Сообщение от Usaga Посмотреть сообщение
Что не так в том, что я советовал? Откуда вырисовывались вещи, которые даже близко не поднимаются в вопросе ТСа?
Не будем ссориться :) Вы не увидели крамолу в массовом вводе и передаче строк за раз, я увидел.
Каждый остался при своем мнении - и это нормально :)



Добавлено через 48 минут
Цитата Сообщение от 7-2-3 Посмотреть сообщение
Получается мне ещё там цикл нужен ?
Не обязательно.

У вас WinForms, поэтому все проще

Есть два варианта:

1. Без перебора строк.
Добавление каждой строки (по кнопке или при потери фокуса текущей, уже заполненной строкой) приводит к добавлению в БД - для этого пишется код, в котором сначала проверяется есть ли новый документ в базе и, если нет, то добавляется новая строка в таблицу заголовков документов. При этом извлекается новый id документа и с ним делается вставка новой записи в таблицу состава. Если id уже сеть (т.е. поле не null в Модели документа), то добавляется только строка.
Все - через ORM с последующим SaveChanges. При этом даже если комп "умрет", то в базе уже будут введенные строчки.

3. С перебором
Сохранение выполняется в конце ввода всех строк специальной "кнопкой". При этом весь документ со всеми строками пишется "скопом" в базу. При этом, если ПК "умер" да нажатия кнопки, все придется повторить. Но сам механизм сохранения тот же, но SaveChanges выполняется в самом конце и лишь раз.
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
12.10.2020, 20:16  [ТС]
Я запутался(
А, тогда вот, Вы писали:
"Можно в свойство DataGridView.DataSource затолкать коллекцию любого класса, а потом получить ссылку на выбранный экземпляр и уже его передать в запрос. Это в 100500 раз удобнее, чем руками по ячейкам бегать"
Это же как раз о том что мне нужно ?


На всякий случай framework поднял до версии 4.6.1 и версия языка 6.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.10.2020, 20:16

Выборка данных из связанных таблиц
Всем привет! Столкнулся с проблемой выборки данных из связанных таблиц.Есть БД Access, читаю с помощью OLEDB. Есть 2 таблицы: 1...

Вывод связанных таблиц в DataGridView
Здравствуйте. Имеются три таблицы: Books (со столбцами ID, Name, Author, Genre), Authors (со столбцами ID, Name, Surname), Genres (со...

Обновление связанных таблиц в DataGridView
Всем привет. Возник такой вопрос: как можно обновить связанную таблицу при программной сортировке главной? Я сортирую результаты главной...

Обновление связанных таблиц в datagridview
Есть кнопка на вывод информации: SqlConnection con; SqlDataAdapter sda; SqlCommandBuilder scb; ...

Отображение полей связанных таблиц
Здравствуйте. Существуют таблицы: Товары, тип товара, категория. &quot;Тип товара&quot; связанны с &quot;категорией&quot;, а &quot;товары&quot; с...


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

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Nekobox - outbounds[0].transport: unknown transport type: raw
damix 01.10.2026
Фикс ошибки Правым кликом по серверу -> отладочная информация -> edit Заменить "net": "raw", на "net": "tcp", Нажать кнопку reload.
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru