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

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

17.05.2020, 11:06. Показов 8780. Ответов 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
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,914
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
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,914
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
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,914
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
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,914
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
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,914
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
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,914
08.10.2020, 03:19
MsGuns, что, простите?
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
08.10.2020, 08:59  [ТС]
Имеется введу, что её 19 набитых строк пропадут даром.
Но мне пока не до проблем Маруси, мне бы главное чтоб моя программуличка хоть как-нибудь заработала)
0
Эксперт .NET
 Аватар для Usaga
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,914
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
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,914
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
Ответ Создать тему
Новые блоги и статьи
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru