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

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

17.05.2020, 11:06. Показов 8791. Ответов 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
05.10.2020, 20:09  [ТС]
Студворк — интернет-сервис помощи студентам
мм, если я правильно понял, то нет.
Мне нужен один ID для всех строк в datagridview, вот как тут было:
T-SQL
1
2
3
4
5
6
7
8
DECLARE @Newid INT 
INSERT INTO Покупки(ПоставщикID, PrihodDate) VALUES (4, getdate())
SET @Newid = SCOPE_IDENTITY()
INSERT INTO ПокупкаИнфо (ПокупкаID, LineItem, ProductID, Qty , Price) 
VALUES                              
(@Newid, 1, 1, 21, 450),  
(@Newid, 2, 3, 11, 550) -- 2 строки, с одни и тем же возвращённым Newid.
GO
0
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
05.10.2020, 22:24
Т.е. добавляется не новый документ с единственной строкой, а документ с произвольным кол-вом строк ?
Тогда хранимкой тут не пахнет
Вернее, можно хранимкой - если написать хранимку, которая будет проверять наличие заголовка в таблице документов и добавлять новый, если нет, с извлечением id. Или использовать id уже записанного. И так в цикле доя всех строк.
Цикл, еснно, на стороне Клиента. И все в одной транзакции.
Но это - плохо.

А вот если взять "отвертку" типа уже присоветанного Вам Dupper, то там все это безобразие лепится легче, прочнее и красивше.

Однако есть тут одна концептуальная вещь.

Дело в том, что сложные многоуровневые сущности типа Вашего документа, хранятся, как правило, в разных таблицах.
Интерфейс работы с этими сущностями надо организовывать правильно.

В данном случае есть список документов (1-й грид) и список строк по текущему выбранному в 1-м гриде документу (2-й грид). Т.е. имеем 2 датасета, связанных отношением "один-ко-многим", отображаемым в двух сетках.
Юзер, "гуляя" про 1-му гриду, видит меняющееся содержимое 2-го грида.

Правка в списке документов:
- Добавление. По введенным данным добавляется новый документ, датасет перечитывается - в результате в 1-м гриде видим только что добавленный документ, а в 2-м гриде - "чисто".
- Изменение. Тут все ясно - изменение неключевых реквизитов документв никак не трогает все его содержимое, т.е. подчиненные строки остаются те же.
- Удаление. Сначала удаляются все подчиненные строки, а потом заголовок. После перечитки в 1-м гриде не будет удаленного заголовка (как и всех строк в подчиненной таблице), а 2-й грид будет показывать детализацию по той строчке 1-го грида, которая станет текущей после удаления.

Правка в списке строк.
Тут все просто, т.к. есть парентский id.

Эти правки не должны быть совместимы ! Т.е. одна форма для работы с заголовком документа, другая - для работы с его содержимым, т.е. строками.

Визуально для юзера такая технология будет намного понятнее нежели добавление "скопом". В частности, он может прервать свою работу в любой момент, запостив последнюю форму. А потом возобновить ее тоже в любой момент.
А как это грамотно сделать, если все надо заводить "разом", а в документе 1000 строк ? Будет конкретный геморрой с какими-то буферами, откатами и подтверждением.
1
Эксперт .NET
 Аватар для Usaga
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
06.10.2020, 07:14
Цитата Сообщение от 7-2-3 Посмотреть сообщение
Мне нужен один ID для всех строк в datagridview, вот как тут было:
Если я правильно понял, то таблица "Покупки" - это материализованная корзина, а "ПокупкиИнфо" - её содержимое.

Если позиций в оплаченной корзине много, то я не вижу проблемы разбить этот запрос на два. В первом вы вносите запись в "Покупки" и получаете ID. Второй собираете в цикле в один пакет (одна строка SQL-запроса) и отправляете в базу. Всё это завернуть в транзакцию, естественно.

В цикле N запросов в базу отправлять не рекомендую. Это не есть эффективно.
0
 Аватар для Andrey-MSK
3397 / 2283 / 388
Регистрация: 14.08.2018
Сообщений: 7,749
Записей в блоге: 4
06.10.2020, 09:18
7-2-3, можно еще использовать DataSet, конкуренция в нем реализована, пакетное обновление тоже. Только нужно в нем правильно настроить адаптеры таблиц, чтоб не грузили лишнего в память. Его можно создать конструктором в VS, все будет красиво и понятно, как на диаграмме в SSMS И будут строго типизированные наборы данных, с которыми оперировать уже гораздо проще.
0
Эксперт .NET
 Аватар для Usaga
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
06.10.2020, 09:58
Andrey-MSK, вряд ли это правильный совет) Этот класс - пережиток прошлого. Да, его можно использовать. Но суммарное количество телодвижений будет если не такое же как с чистым классом и парой запросов, то даже больше. А в наглядности код явно проиграет.
0
 Аватар для Andrey-MSK
3397 / 2283 / 388
Регистрация: 14.08.2018
Сообщений: 7,749
Записей в блоге: 4
06.10.2020, 10:20
Usaga, а чего там много телодвижений будет? Создал библиотеку классов, сделал там DataSet с парой таблиц и связями (все делается мышой ). Получилось два адаптера и восемь методов - два Fill(настраивается для выгрузки только того что надо) и по два Update, Insert, Delete. Потом создал проект WinForms, подключил свой DAL и используй восемь методов и два адаптера. Остальное, что внутри сборки с DAL, волновать не должно. Тем более ТС пишет на WF, а DataSet как раз для него
Если надо еще таблицу добавить в DAL, открываешь проект, правишь схему, сохраняешь и пересобираешь. Появится еще один адаптер и четыре метода А если просто запрос на выборку туда добавить, то появится только один адаптер и один метод.
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
06.10.2020, 10:39  [ТС]
Если позиций в оплаченной корзине много, то я не вижу проблемы разбить этот запрос на два. В первом вы вносите запись в "Покупки" и получаете ID. Второй собираете в цикле в один пакет (одна строка SQL-запроса) и отправляете в базу. Всё это завернуть в транзакцию, естественно.

А можно поподробнее ?
0
Эксперт .NET
 Аватар для Usaga
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
06.10.2020, 10:53
Цитата Сообщение от 7-2-3 Посмотреть сообщение
А можно поподробнее ?
А я не подробно описал?)
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
06.10.2020, 14:39  [ТС]
Ну, в принципе как бы, мысль вроде понятна, но мне хотя примерчик бы какой-нибудь, а то даже практиковаться не получается)
0
Эксперт .NET
 Аватар для Usaga
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
06.10.2020, 14:53
7-2-3, примерчик чего? Как запрос в базу отправить? Так вы сами это умеете, если судить по первой странице этой темы. С текстом запроса тоже уже определились. Что ещё надо?)
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
06.10.2020, 16:54  [ТС]
мм, а эти два запроса должны у меня срабатывать с одной кнопочки, объединённые в одной транзакции ?

Я просто изначально, делал примерно так(просто ради эксперимента):
Создал 2 кнопки, в одной отправлялись данные в таблицу Покупки, а во второй(ПокупкиИнфо) приходилось в datagreedview ставить вручную ID.
0
Эксперт .NET
 Аватар для Usaga
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
06.10.2020, 16:57
Цитата Сообщение от 7-2-3 Посмотреть сообщение
мм, а эти два запроса должны у меня срабатывать с одной кнопочки, объединённые в одной транзакции ?
Ну это, как бы, логично) У вас есть одно действие (с точки зрения UI): сохранить изменения. Значит одна кнопка. И транзакция обязательна, так как у вас несколько команд изменения данных. Они либо все должны отработать корректно, либо ни одна не должна.
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
06.10.2020, 21:26  [ТС]
Пока вот только первая процедура для возврата ID в приложение (и то вызывает сомнения):
T-SQL
1
2
3
4
5
6
7
8
9
10
11
CREATE PROC dbo.NewID2
@ПоставщикID int,
 @PrihodDate Date
 AS
    --SET NOCOUNT ON    
    DECLARE @NewID int
    INSERT INTO Покупки
    VALUES 
    (@PrihodDate,@ПоставщикID ) 
 
    SET @NewID = SCOPE_IDENTITY()
Получается я получаю ID в NewID, и никуда его не вставляю ?

Вот моя многострадальная кнопочка(пока только без ПокупкиИнфо):
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
   private void button3_Click(object sender, EventArgs e)
        {         
            if (comboBox1.Text == "")
            {
                MessageBox.Show("Заполните все поля!");
            }
            else
            {
                try
                {
 
                   // SqlTransaction transaction = conn.BeginTransaction();
                    int ПоставщикID = int.Parse(label22.Text);
                    DateTime PrihodDate = Convert.ToDateTime(dateTimePicker1.Text);
                    
                  
                    conn = new SqlConnection();
                    conn.ConnectionString = @"Data Source=RR-PC\SQL150916;Initial Catalog=Base5;Integrated Security=True";
                    SqlCommand myCommand = new SqlCommand("INSERT INTO [Покупки] ([ПоставщикID], PrihodDate) VALUES (@ПоставщикID, @PrihodDate);set @NewID = SCOPE_IDENTITY()", conn);
                    // SqlCommand myCommand = conn.CreateCommand();
                    myCommand.CommandType = CommandType.StoredProcedure;
                    myCommand.CommandText = "[NewID2]";
 
                    myCommand.Parameters.Add("@PrihodDate", SqlDbType.DateTime, 8);
                    myCommand.Parameters["@PrihodDate"].Value = PrihodDate;
 
                    myCommand.Parameters.Add("@ПоставщикID", SqlDbType.Int, 4);
                    myCommand.Parameters["@ПоставщикID"].Value = ПоставщикID;
 
                    myCommand.Parameters.Add("@NewID", SqlDbType.Int, 4);
                    myCommand.Parameters["@NewID"].Direction = ParameterDirection.Output;
                   // myCommand.Transaction = transaction;
                
                    conn.Open();
                    myCommand.ExecuteScalar();
 
                     string New_ID;
                     New_ID = Convert.ToString(myCommand.Parameters["@NewID"].Value);
                     textBox5.Text = New_ID;
 
                    myCommand.ExecuteNonQuery();
                   // transaction.Commit();
              
                }
                
                finally
                {
                    conn.Close();
                    comboBox1.SelectedIndex = -1;
                }
                this.покупкиTableAdapter1.Fill(this.base5DataSet13.Покупки);
                this.tabControl1.SelectedTab = tabPage1;
            }
        }
Запускаю, получаю вот это:
Дополнительные сведения: Для процедуры или функции NewID2 указано слишком много аргументов.


Я хотел пока вставить ID в переменную New_ID, не получилось(
0
Эксперт .NET
 Аватар для Usaga
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
07.10.2020, 04:39
7-2-3, да блин. Вот так это может выглядеть с применением Dapper.NET:

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

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
using System;
using System.Data.SqlClient;
using System.Transactions;
 
// Чтобы это ns стало доступно
// нужно установить NuGet-пакет "Dapper"
using Dapper;
 
namespace ConsoleApp
{
    class OrderItem
    {
        public int OrderId { get; set; }
 
        public int LineItem { get; set; }
 
        public int ProductId { get; set; }
 
        public int Qty { get; set; }
 
        public decimal Price { get; set; }
    }
 
    class App
    {
        public static void Main()
        {
            using (var con = new SqlConnection(@"Data Source=RR-PC\SQL150916;Initial Catalog=Base5;Integrated Security=True"))
            {
                using (var tran = new TransactionScope())
                {
                    // Вносим покупку
                    var orderId = con.QueryFirst<int>(@$"
                        INSERT INTO Orders (VendorId, SupplyDate)
                        VALUES (@VendorId, @SupplyDate);
 
                        SELECT SCOPE_IDENTITY()",
                        
                        /* можем использовать анонимные типы */
                        new { VendorId = 100500, SupplyDate = DateTime.Now });
 
                    // Откуда-то получаем список товара
                    // В данном случае заполняем руками
                    // Каждой позиции выставляем ранее полученный orderId
                    var orderItems = new[]
                    {
                        new OrderItem { OrderId = orderId, LineItem = 1, ProductId = 2, Qty = 3, Price = 4m },
                        new OrderItem { OrderId = orderId, LineItem = 2, ProductId = 3, Qty = 4, Price = 5.5m }
                    };
 
                    // Вносим товар
                    // Dapper сам догадается, что команду нужно повторить N раз,
                    // когда увидит, что в параметрах коллекция
                    con.Execute(@$"
                        INSERT INTO OrderItems (OrderId, LineItem, ProductID, Qty, Price)
                        VALUES (@OrderId, @LineItem, @ProductID, @Qty, @Price)", orderItems);
 
                    tran.Complete();
                }
            }
        }
    }
}


Dapper сам за вас всё сделает. Я же не просто так вам эту штуку рекомендовал посмотреть.
1
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
07.10.2020, 11:50  [ТС]
Установил Install-Package Dapper -Version 1.42.0.

Застрял с директивой: using System.Transactions;
VS, почему то считает что она не нужна, как её победить не знаю.
Миниатюры
ID связанных таблиц 2  
0
Эксперт .NET
 Аватар для Usaga
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
07.10.2020, 12:00
Цитата Сообщение от 7-2-3 Посмотреть сообщение
Установил Install-Package Dapper -Version 1.42.0.
Не, актуальная версия даппера - 2.0.35. Вы что-то совсем старое поставили.

Цитата Сообщение от 7-2-3 Посмотреть сообщение
Застрял с директивой: using System.Transactions;
Вызовите контекстное меню на элементе "Ссылки":



Затем найдите и поставьте галочку:
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
07.10.2020, 12:09  [ТС]
Последняя версия dapper, не хотела ставиться в решение, ругается при установке на версию framework 4.5.2(видимо ему такая нужна).
0
Эксперт .NET
 Аватар для Usaga
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
07.10.2020, 12:10
7-2-3, а, может быть) Я бы просто поднял версию .NET Framework в проекте минимум до 4.6.1. А лучше сразу до максимальной - 4.8
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
07.10.2020, 14:38  [ТС]
А вот тут ему моя собачка не нравится:
Миниатюры
ID связанных таблиц 2  
0
Эксперт .NET
 Аватар для Usaga
14745 / 9519 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
07.10.2020, 14:51
7-2-3, версию языка C# поднимите. И версию .NET Framework. Или не используйте эту фичу) Я это использовал только, чтобы текст запроса красиво и читаемо в коде выглядел. Не более того.

Добавлено через 2 минуты
Или поменяйте местами доллар и собачку.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.10.2020, 14:51

Выборка данных из связанных таблиц
Всем привет! Столкнулся с проблемой выборки данных из связанных таблиц.Есть БД 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; с...


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Программа опроса у.з. расходомера 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