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

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

17.05.2020, 11:06. Показов 8883. Ответов 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
Эксперт .NET
 Аватар для Usaga
14789 / 9562 / 1367
Регистрация: 21.01.2016
Сообщений: 36,058
14.10.2020, 06:38
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от MsGuns Посмотреть сообщение
Не будем ссориться Вы не увидели крамолу в массовом вводе и передаче строк за раз, я увидел.
Каждый остался при своем мнении - и это нормально
Крамола это или нет определяется конкретными требованиями для каждого отдельного кейса.

Цитата Сообщение от 7-2-3 Посмотреть сообщение
Я запутался(
MsGuns, вам о двух разных подходах: первый - про сохранение данных по мере их ввода. Второй - про однократное сохранение данных сразу всей пачкой.

Я вам показал пример (тот, что с Dapper'ом) именно второго подхода. Он существенно проще. А вопрос надёжности (что ваше приложение не упадёт или свет не выключат) тут явно смысла не имеет.

Цитата Сообщение от 7-2-3 Посмотреть сообщение
"Можно в свойство DataGridView.DataSource затолкать коллекцию любого класса, а потом получить ссылку на выбранный экземпляр и уже его передать в запрос. Это в 100500 раз удобнее, чем руками по ячейкам бегать"
По формулировке похоже, что это я писал) И да, это часть того, что вам нужно: просто коллекцию, которую отредактировали через DataGridView передать указанным мной выше способом в Dapper, а тот уже сам всё сохранит.

Но у меня уже закончилось терпение на пальцах каждое слово объяснять, уж извините. Погуглите использование List<T> с DataGridView. А уж передать List<T> в Dapper я думаю вы сможете, благо я тут даже пример выкладывал (правда там массив, а не List<T>, но для Dapper'а это не важно).

В общем, попробуйте поналегать на гугл. Все нужные подходы и технологии вам тут уже назвали.
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
10.01.2021, 23:08  [ТС]
После выздоровления решил вернуться к своей задачке.
Погуглил использование List<T> с DataGridView, но нашлись в основном примеры в которых из нескольких textbox(с помощью List) вставляют строки в DataGridView. А мне нужно из ячеек DataGridView запихнуть данные в таблицу SQL.
Слямзил с просторов интернета примерно такой код:
Кликните здесь для просмотра всего текста
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
 
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; }
        }
 
//-------------------------------------------------------------
var list = new List<OrderItem>()
                  {
                        new OrderItem { покупкаID = orderId },
                        new OrderItem { LineItem = ?},
                        new OrderItem { ProductID = ?},
                        new OrderItem { Qty = ? },
                        new OrderItem { Price = ? }
                  };
                    var bindingList = new BindingList<OrderItem>(list);
                    var source = new BindingSource(bindingList, null);
                    dataGridView4.DataSource = source;

Но вот вместо вопросиков ("?") не знаю что вставить? Наверное индекс столбца и тип данных?
Нужен как то подходящий наглядный примерчик(
0
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
11.01.2021, 01:17
Лучший ответ Сообщение было отмечено 7-2-3 как решение

Решение

Вы взяли не Ваш пример.
В нем (примере) показано как добавлять записи модели OrderItem в список, а затем этот список отобразить в гриде автоматически.
При этом в приведенном Вами коде видно "ошибка" копирования: создается 5 записей (объектов-моделей OrderItem), в каждой из который заполняется только по одному полю. Явно напутали что-то с new.

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

Но главное - какой-либо связи с конкретной таблицей или запросом БД в этом примере нет !

Вам нужно:
1) Создать Модели (Например в dapper), являющиеся отображением конкретных таблиц БД.
2) Получить методы контекста типа DBSet (Но это в EF, в Dapper - не знаю, не юзал) для получения интерфейса с "живыми" таблицами БД.
3) Связать гриды через DataSource с этими DBSet`ами, приведенными к списку (ToList). При этом "причесать" грид, убрав из показа колонку с Id и заменив заголовки на русские. (И то, и другое можно и нужно делать через специальные директивы [] в самой модели-классе)
В результате после выполнения кода обновления источника данных (DataSource) каждый грид будет показывать информацию "своей" таблицы.

Это - отображение.

Добавлено через 23 минуты
Редактирование.

1. Есть понятие фокус. Т.е. тот прямоугольник-ячейка, куда он может что-то вводить. Эта ячейка соответствует активной колонке активной строки грида и одновременно полю активной записи датасета.
Т.е. в каждый момент времени редактируется одно поле одного объекта класса-модели. При переводе фокуса из одной ячейки строки в другую идет переход из одного поля объекта в другое.
При переводе курсора на другую строку происходит переход от одного объекта-класса к другому.

2. Если Вы не предусмотрели никаких действий, то по кнопке "Сохранить" все измененные (в т.ч. добавленные и удаленные) записи датасета будут интерпретированы Dapper автоматически в SQL-запросы, которые и отправятся на SQL-сервер.
При этом Вам не нужно заботиться ни о каких Id связок - все будет выполнено автоматом.
Однако Вы должны обеспокоиться тем, чтобы на сервер не полетели ошибки - например юзер не ввел обязательные значения либо ввел с ошибками (например нецифра для числового поля). Это, кстати, можно также вменить в обязанность "умному" ORM - в этом случае до отправки на сервер дело не дойдет вообще - эксепшн будет поднят непосредственно в Вашем приложении.

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

4. Удаление.
По кнопке "удалить" текущий объект удаляется из списка (датасета) обычным образом.

ВАЖНО !!!
Все вышеописанные действия выполняется в кэше изменений Dapper, но никак не отражаются в БД !!!
Для того, чтобы все это "легло" в БД надо дать специальную команду, о чем было написано выше.

Добавлено через 7 минут
5. Доступ к "ячейкам".
Он нужен например, для проверки значения, введенного пользователем. Или для реализации некоторой смысловой нагрузки, когда есть взаимосвязь между несколькими полями записи. (Например, если указано кол-во, то должна быть и цена и т.д.)
Т.к. Вы работаете с моделью, Вам не нужно обращаться к "ячейкам"-элементам массива, используя индексацию.
Вы можете получить доступ к любой строке грида (она же запись, она же объект-модель) через индекс списка.
Или получить текущий объект через activeRecord датасета.
Далее для того, чтобы обратиться к любому полю объекта, просто пишете его имя. Как это принято в ООП. И все.
Красиво, прозрачно, лаконично
1
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
11.01.2021, 21:24  [ТС]
Я почитал про dapper, посмотрел несколько роликов, и получается , что информации масса, а что использовать в конкретно моём случае не понятно.
Вот это и есть модель ?
C#
1
2
3
4
5
6
7
8
9
10
11
12
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; }
        }
Вот тут сейчас читаю: https://metanit.com/sharp/articles/mvc/dapper.php

Добавлено через 28 минут
Из переделанного примера достопочтенного Usaga:
Кликните здесь для просмотра всего текста
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
  private void button3_Click(object sender, EventArgs e)
        {
            int ПоставщикID = int.Parse(label22.Text);
            DateTime PrihodDate = Convert.ToDateTime(dateTimePicker1.Text);
             using (var conn = new SqlConnection(@"Data Source=RR-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 = int.Parse(label22.Text), PrihodDate = DateTime.Now });
 
                    // Откуда-то получаем список товара
                
                    // В данном случае заполняем руками
                    // Каждой позиции выставляем ранее полученный orderId
                    var orderItems = new[]
                         { 
                        new OrderItem { покупкаID = orderId, LineItem = 1, ProductID = 1, Qty = 55, Price = 355 },
                        new OrderItem { покупкаID = orderId, LineItem = 2, ProductID = 2, Qty = 321, Price = 432 } ,
                        new OrderItem { покупкаID = orderId, LineItem = 3, ProductID = 3, Qty = 43, Price = 512 }                      
                         };
 
                    // Вносим товар
                    // Dapper сам догадается, что команду нужно повторить N раз,
                    // когда увидит, что в параметрах коллекция                   
                        conn.Execute($@"INSERT INTO ПокупкаИнфо(ПокупкаID, LineItem, ProductID, Qty, Price) VALUES (@ПокупкаID, @LineItem, @ProductID, @Qty, @Price)", orderItems);
                    
                   // this.покупкиTableAdapter1.Fill(this.base5DataSet13.Покупки);
                    tran.Complete();
 
                    this.tabControl1.SelectedTab = tabPage1;


Из всего этого я полагал, что достаточно изменить код, вместо рукописного массива:
C#
1
2
3
4
5
6
  var orderItems = new[]
                         { 
                        new OrderItem { покупкаID = orderId, LineItem = 1, ProductID = 1, Qty = 55, Price = 355 },
                        new OrderItem { покупкаID = orderId, LineItem = 2, ProductID = 2, Qty = 321, Price = 432 } ,
                        new OrderItem { покупкаID = orderId, LineItem = 3, ProductID = 3, Qty = 43, Price = 512 }                      
                         };
Прописать List , и всё заработает, нет разве?)
0
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
12.01.2021, 01:39
Цитата Сообщение от 7-2-3 Посмотреть сообщение
Прописать List , и всё заработает, нет разве?
А примере создается новый список объектов классов-моделей и суется в грид.

У Вас же есть таблица БД. Которой сопоставлена модель. В грид кладется датасет, полученный запросом из таблицы БД и приведенный к List<OrderItem>.
При этом все объекты уже есть ! И редактирование в гриде приводит к изменению полей этих самых объектов. При этом можно делать правки по всему гриду (датасету) - изменения сохраняются в кэше Dapper.
Затем кнопкой делается сохранение изменений в базу скопом, кучей. За один раз.

Создание нового объекта выполняется отдельной кнопкой "ручным" кодом - при этом создается один экземпляр класса-модели OrderItem, при этом инициализируются его поля (в конструкторе или опять же в коде обработчика кнопки). После этого опять же кодом этот объект вставляется в List, привязанный к гриду.

Можно обойтись и без кнопки, соответствующим образом настроив грид. Тогда создание, инициализация и добавление в лист объектов (в самый его конец) будет выполнено автоматически - никакого кода писать не придется.

Иными словами, оператор new нужно использовать лишь при добавлении новой записи. И он вовсе не нужен для добавления всего списка (всех полученных от сервера записей таблицы БД).

Добавлено через 10 минут
Упомянутая Вами статья про Dapper не слишком удачна, т.к. пример в ней реализован для Web MVC и в нем ничего нет про отображение данных и их редактирование. Логика работы с ORM из примера (класс UserRepository) вполне подходит, а вот все, что связано с отображением и правкой (DataGridView) надо искать в других местах.
0
Эксперт .NET
 Аватар для Usaga
14789 / 9562 / 1367
Регистрация: 21.01.2016
Сообщений: 36,058
12.01.2021, 06:44
Цитата Сообщение от MsGuns Посмотреть сообщение
изменения сохраняются в кэше Dapper.
У даппера есть Change Tracking? С каких пор?
1
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
12.01.2021, 14:16
Цитата Сообщение от Usaga Посмотреть сообщение
У даппера есть Change Tracking? С каких пор?
Это мои "догадки"
Я полагал, что он так же умен, как EF

Спасибо за поправку.
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
12.01.2021, 20:08  [ТС]
"и этом можно делать правки по всему гриду (датасету) - изменения сохраняются в кэше Dapper" - а где же тогда сохраняются изменения ?


Добавлено через 29 минут

Нашёл ещё пример, но там datagridview просто отображает данные из БД:
https://foxlearn.com/articles/... p-141.html

В большинстве примеров, источником для DataGridView является List, а не наоборот.
0
54 / 6 / 5
Регистрация: 24.01.2019
Сообщений: 171
23.01.2021, 19:19  [ТС]
В голове ещё каша, но кое-что стало понятно.)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
23.01.2021, 19:19

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


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

Или воспользуйтесь поиском по форуму:
89
Ответ Создать тему
Новые блоги и статьи
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 и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера 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) активировать флаг. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru