68 / 8 / 1
Регистрация: 14.03.2013
Сообщений: 116
|
||||||||||||||||
1 | ||||||||||||||||
Использование столбцов с автоинкрементом без конфликтов (ADO.NET)17.02.2014, 19:45. Показов 2879. Ответов 10
Метки нет (Все метки)
Привет участникам форума !
Хочу обратиться за помощью по проблеме обновления DataTable c автоинкрементом. Одно из решений повседневной задачи использования столбцов с автоинкрементом хорошо известно и состоит в настройке ключевого столбца в exampleDataSet.Tables("exampleDataTable").Columns("id") так:
Тогда при выполнении обновления данных:
Проблема состоит в том, что поле заполнения таблицы exampleDataTable уже обновленными строками с SQL сервера в exampleDataTable остаются копии первоначальных строк с отрицательными значениями столбца "id". Вот как-то же exampleDataAdapter должен понимать, что это есть старые версии обновленных строк и автоматических их ликвидировать? Или нет?
0
|
17.02.2014, 19:45 | |
Ответы с готовыми решениями:
10
ADO.NET OleDbDataReader и OleDbCommand проблема чтения из Excel файла, DataReader не получает некоторые ячейки из столбцов Использование DirectX без NET оберток Удаленный SQL-сервер Ado.Net + .Net remoting + Asp .Net Как без конфликтов с СКУД получать доступ к её БД из модуля C# |
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
|
|||||||||||
18.02.2014, 07:27 | 2 | ||||||||||
Сообщение было отмечено Bars4 как решение
Решение
Можно настроить DataAdapter так, чтобы он он при вызове Fill перезаписывал старые строки новыми. Но вам это не поможет, так как идентификация таких строк происходит по первичному ключу, а у вас он заведомо ложный до создания записей в СУБД.
Данная проблема решается в одну строку:
1
|
68 / 8 / 1
Регистрация: 14.03.2013
Сообщений: 116
|
||||||||||||||||
18.02.2014, 14:27 [ТС] | 3 | |||||||||||||||
kodv, спасибо! Насчет нерациональности с ложными "id" согласен однозначно.
В варианте с exampleDataTable.Clear так же возникает дополнительная трудность, если exampleDataTable имеет exampleDataRelation. А что будет с данными, если в дочернюю таблицу examplechldDataTable будут добавлены записи еще до обновления родительской ? Так же я пытался устанавливать действительно очередной "id" как-то так:
Т.е. неслучайность последовательности налицо, но источник пропусков так и не смог объяснить. Предложенный Вами код:
А такой вариант будет работать без пропусков "id" ?
0
|
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
|
|
18.02.2014, 15:15 | 4 |
Сообщение от Bars4
1
|
68 / 8 / 1
Регистрация: 14.03.2013
Сообщений: 116
|
||||||||||||||||
18.02.2014, 17:27 [ТС] | 5 | |||||||||||||||
Проблема возникла с тем, что столбец "id" является ключевым и соответственно обработчик события exampleDataAdapter_RowUpdated:
0
|
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
|
|
18.02.2014, 18:47 | 6 |
Bars4, чтобы внести ясность в терминологию.
Ключевое поле не является доступным только для чтения. Его можно менять сколько угодно, его единственное ограничение - это уникальность каждого значения среди остальных значений данного столбца. Поле IDENTITY менять нельзя, но данное поле располагается в таблице СУБД. В объекте DataTable в .NET находится AutoIncrement-поле. Различия не только в название, в DataTable данное поле можно легко менять, чего в СУБД сделать не удастся. Специально не стал отвечать с телефона, а включил ноут и проверил данное утверждение. У колонки в DataTable может быть задано свойство ReadOnly = true. Если это так, то поле в DataTable изменить уже не получится. Так вот. Утверждать не буду, с высокой вероятностью исключение вы ловите из-за того, то сами изменили свойство ReadOnly для ключевых столбцов. Проверьте, и, если это так, то измените значение этого свойтсва на false. PS: Только сейчас обратил, что вы на Visual Basic пишите, в том числе и в первом посте. По хорошему вас нужно было бы в другой раздел отправить - здесь зона C#.
1
|
68 / 8 / 1
Регистрация: 14.03.2013
Сообщений: 116
|
||||||
18.02.2014, 23:41 [ТС] | 7 | |||||
Виноват, если разместился в разделе, не соответствующем тематике вопроса, но я ориентировался на ADO.NET. Прошу перенести тему в раздел по назначению.
И в действительности вы правы, дело не в ReadOnly столбца. Ваше решение верно на 100 % и его я уже где-то встречал в литературе. В моем же случае ошибка возникает уже здесь:
0
|
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
|
|
19.02.2014, 02:54 | 8 |
Bars4, возможно - это из-за scope_identity. Я обычно в таких случаях использую @@identity, но увидев, что вы пишите про scope_identity вставил его. @@identity ,может выдать не верный результат в случае наличия триггеров, а у scope_identity область действия - это пакет, функция или хп. То есть, в данном случае команда может восприниматься как в отдельном от вставки пакете. попробуйте использовать @@identity.
1
|
68 / 8 / 1
Регистрация: 14.03.2013
Сообщений: 116
|
|||||||||||
19.02.2014, 23:01 [ТС] | 9 | ||||||||||
kodv, за терпение спасибо.
Мои пробелы в знании матчасти очевидны. Однако выцыганивание ответов на форуме всегда интереснее, чем сухая техдокументация. Попробовал, код:
Может (нужны танцы с бубнами) не допустимо/не рекомендуется выпонять команды Update и Fill для одного и того же DataTable на одном и том же экземпляре Connection, Command и Adapter ? ЗЫ: в литературе я нигде не встречал обязательности установки значения свойства AutoIncrementSeed. Значит, хотите ставьте, хотите нет. При этом установка только AutoIncrement в тру, формирует на первый взгляд адэкватную последовательность id. Тогда зачем бы в книгах рекомендовали exampleDataAdapter_RowUpdated? Если есть ИМХО по этому поводу, прошу поделиться.
0
|
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
|
||||||
20.02.2014, 10:35 | 10 | |||||
Сообщение было отмечено Bars4 как решение
Решение
Матчасть полностью знать невозможно. Сам полез в MSDN, чтобы дать вам полноценный ответ и не соврать.
На самом деле в MS SQL Server есть еще и третья функция, для получения последнего вставленного идентификатора. Сначала цитата из MSDN: Кликните здесь для просмотра всего текста
Оптимальной функции для считывания последенго вставленного значения не существуют. У каждой есть свои подобные камни: - IDENT_CURRENT возвращает id последней вставленной записи в конкретную таблицу, но он не дает гарантии, что будет ид именно той записи, которую вставили вы. Это может быть ид записи, который была вставлена после вашей, но до того, как вызвали функцию IDENT_CURRENT. - @@IDENTITY возвращает id последней вставленной записи в рамках сеанса, но в случае совершения скрытых действий (триггеров) может вернутся id не той записи, которую вы ожидаете. Но если вы знаете. что у вас на нужной таблице нет и не будет триггеров, которые бы могли сбить с толку @@IDENTITY, то можно смело использовать его. - SCOPE_IDENTITY возвращает нужный, ожидаемый id, но только в том случае, если команда вставки и считывания id'а будут выполнены в одном пакете. То есть, для обработки события RowUpdated она не подходит. Зато она лучше остальных подходит для второго способа получить идентификатор новой записи. Немножко про второй способ. Он менее универсальный, чем первый, но для SQL Server'а подходит. Можно для вставки написать хранимую процедуру, или составить параметризированный запрос, который вместе со вставкой записи будет возвращать значение нового идентификатора в OUTPUT параметре. После этого вам останется у этого OUTPUT параметра указать SourceColumn = "id", и SqlDataAdapter сам автоматически обновит все ваши иды после вставки записей в базу данных. Внутри этой хранимой процедуру можно смело использовать SCOPE_IDENTITY() для получения вставленного id'а.
1
|
68 / 8 / 1
Регистрация: 14.03.2013
Сообщений: 116
|
|
20.02.2014, 16:00 [ТС] | 11 |
kodv, спасибо за развернутый ответ. Доходчиво и исчерпывающе разжевано.
Добавлено через 4 часа 13 минут Так же считаю последний ответ kodv следует поместить в зеленую рамку и закрепить на форуме, т.к. в нем подведены толковые резюме и пояснения по поводу работы с IDENTITY на ADO.NET. Многим это будет полезным.
0
|
20.02.2014, 16:00 | |
20.02.2014, 16:00 | |
Помогаю со студенческими работами здесь
11
Отличия ADO.NET'03 и ADO.NET'05 Сколько столбцов с автоинкрементом можно создать в одной таблице MySQL? SQLite+Entity Framework+NET4.0 Без ADO NET, и App.config, packages.config Возможно ли использование классов .Net на системе без установленного фреймворка? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |