|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
У меня есть .NET 4.6 программа, работающая с SQL Server 2012. Возникла такая задача: в некоей точке программы сделать нечто вроде rollback-а для объекта, производного от System.Data.DataSet. То есть в некий момент сохранить всё что есть в этом объекте (и схему данных, и сами данные); а потом – восстановить. Впрочем – “схема данных” изменяться и не будет; задача сужается до “сохранить данные DataSet-a, а позже восстановить их”. Вроде как это можно сделать используя методы Copy(), Clear() и Merge(). Но так как я никогда такого не выполнял, хочу спросить – нет ли тут каких “засад”, с первого взгляда не очевидных? Вообще, мне это вот зачем нужно – чтобы повторить "упавшую" операцию с базой. Примерно так: MyClassDerivedFromDataSet myDataSetObj; <заполнение myDataSetObj данными>; …. <сохранить данные myDataSetObj в некоем myDataSetObjCopy>; <начало транзакции>; <операция DbDataAdapter.Update(myDataSetObj, …). Она заносит данные myDataSetObj в базу, а потом обновляет myDataSetObj данными, возвращёнными из базы>; If <операция выше failed> { <откатить транзакцию>; <восстановить данные myDataSetObj из myDataSetObjCopy>; <повторно выполнить (тоже в транзакции) операцию DbDataAdapter.Update(myDataSetObj, …).> } …. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.06.2018, 23:06 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
KellyLynchУ меня есть .NET 4.6 программа, работающая с SQL Server 2012. Возникла такая задача: в некоей точке программы сделать нечто вроде rollback-а для объекта, производного от System.Data.DataSet. То есть в некий момент сохранить всё что есть в этом объекте (и схему данных, и сами данные); а потом – восстановить. Впрочем – “схема данных” изменяться и не будет; задача сужается до “сохранить данные DataSet-a, а позже восстановить их”. Вроде как это можно сделать используя методы Copy(), Clear() и Merge(). Но так как я никогда такого не выполнял, хочу спросить – нет ли тут каких “засад”, с первого взгляда не очевидных? Вообще, мне это вот зачем нужно – чтобы повторить "упавшую" операцию с базой. Примерно так: MyClassDerivedFromDataSet myDataSetObj; <заполнение myDataSetObj данными>; …. <сохранить данные myDataSetObj в некоем myDataSetObjCopy>; <начало транзакции>; <операция DbDataAdapter.Update(myDataSetObj, …). Она заносит данные myDataSetObj в базу, а потом обновляет myDataSetObj данными, возвращёнными из базы>; If <операция выше failed> { <откатить транзакцию>; <восстановить данные myDataSetObj из myDataSetObjCopy>; <повторно выполнить (тоже в транзакции) операцию DbDataAdapter.Update(myDataSetObj, …).> } …. операция DbDataAdapter.Update(myDataSetObj, …) имеет опцию - FillDuringUpdate что ли, ставь false и если коммит нормальный сам сделай AsseptChanges, иначе нифига не делай или повтори ... |
|||
:
Нравится:
Не нравится:
|
|||
02.06.2018, 00:30 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
... |
|||
:
Нравится:
Не нравится:
|
|||
02.06.2018, 00:33 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
KellyLynch, Ds жив бродяга ( еще пользуются) DS можно сохранить в xml файл со связями а потом поднять с диска в нужный момент, но имхо такой жирной архитектурой в контексте базы данных ( как прокси) не стоит пользоваться. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.06.2018, 18:51 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
Где-то в степиKellyLynch, Ds жив бродяга ( еще пользуются) DS можно сохранить в xml файл со связями а потом поднять с диска в нужный момент, но имхо такой жирной архитектурой в контексте базы данных ( как прокси) не стоит пользоваться. Правильно ли я понял из Вашего ответа, что НЕ получится сделать это так, как я намеревался в исходном посте - " сделать используя методы Copy(), Clear() и Merge() " ? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.06.2018, 17:45 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
KellyLynch, я не помню, >10 лет им не пользовался, да и студию года три не открывал. но запись вроде выглядела по другому гы эта же приблуда для портфельных данных as толстых клиентов, может использоваться не как прокси а как сурагат удаленной базы жалкое подобие на sqlite ... |
|||
:
Нравится:
Не нравится:
|
|||
03.06.2018, 18:54 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
KellyLynch, Это монструозное чудовище неимоверно жрет память, да и если моя память не изменяет, там были проблемы с уборкой мусора в таблицах, лучше прикрутите на его место sqlite + синхронизацию с основной базой. по принципу : выстрелил - забыл ... |
|||
:
Нравится:
Не нравится:
|
|||
03.06.2018, 19:01 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
Где-то в степиKellyLynch, Это монструозное чудовище неимоверно жрет память, да и если моя память не изменяет, там были проблемы с уборкой мусора в таблицах, лучше прикрутите на его место sqlite + синхронизацию с основной базой. по принципу : выстрелил - забыл "лучше прикрутите на его место sqlite ..." - рад бы, да не могу : есть огромная старая программа, которая вся "сидит" на DataSet-ах. Так что придётся возиться с DataSet-ами. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.06.2018, 16:35 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
ViPRos https://msdn.microsoft.com/en-us/library/system.data.common.dataadapter.acceptchangesduringupdate(v=vs.110).aspx Спасибо за ответ. Но я боюсь что это ( https://msdn.microsoft.com/en-us/library/system.data.common.dataadapter.acceptchangesduringupdate(v=vs.110).aspx) мне не подойдёт. Тут я сам виноват – я слишком упростил тот свой пример: <операция DbDataAdapter.Update(myDataSetObj, …). Она заносит данные myDataSetObj в базу, а потом обновляет myDataSetObj данными, возвращёнными из базы>; If <операция выше failed> А в реальности там мне одна операция <операция DbDataAdapter.Update(myDataSetObj, …). Она заносит данные myDataSetObj в базу, а потом обновляет myDataSetObj данными, возвращёнными из базы> , а несколько (одна за другой). И вот что происходило. Выполнилась первая из них. DataSet обновился данными из базы (что зорошо и правильно). Начала выполняться вторая из этих операций. Она “упала”. Я делаю rollback для DB-транзакции и хочу снова выполнить всю последовательность операций DbDataAdapter.Update(myDataSetObj, …). Но DataSet-то уже “грязный”. Если же я в начале поставлю DbDataAdapter.AcceptChangesDuringUpdate = false, то да – DataSet вообще не будет обновляться данными из базы. Но это тоже плохо! Мой код как раз рассчитан на то что первая операция DbDataAdapter.Update(myDataSetObj, …) обновит DataSet данными из базы; а вторая DbDataAdapter.Update(myDataSetObj, …) как раз использует эти обновления. То есть то что “DataSet обновляется данными из базы” – это так и должно быть в моей логике. Но мне надо чтобы если некая из “DbDataAdapter.Update(myDataSetObj, …).” Упадёт – я бы мог восстановить DataSet теми данными, которые были в нём в самом начале. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.06.2018, 17:21 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
KellyLynchЕсли же я в начале поставлю DbDataAdapter.AcceptChangesDuringUpdate = false, то да – DataSet вообще не будет обновляться данными из базы. Будет. Просто не будут эти изменения зафиксированы автоматически. KellyLynchТо есть то что “DataSet обновляется данными из базы” – это так и должно быть в моей логике. Но мне надо чтобы если некая из “DbDataAdapter.Update(myDataSetObj, …).” Упадёт – я бы мог восстановить DataSet теми данными, которые были в нём в самом начале. Так и есть. Если все нормально, то делаешь AcceptChanges, иначе RejectChanges. Ты не паникуй, а пробуй. Все будет нормально. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.06.2018, 17:54 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
[img=] ViPRosKellyLynchЕсли же я в начале поставлю DbDataAdapter.AcceptChangesDuringUpdate = false, то да – DataSet вообще не будет обновляться данными из базы. Будет. Просто не будут эти изменения зафиксированы автоматически. KellyLynchТо есть то что “DataSet обновляется данными из базы” – это так и должно быть в моей логике. Но мне надо чтобы если некая из “DbDataAdapter.Update(myDataSetObj, …).” Упадёт – я бы мог восстановить DataSet теми данными, которые были в нём в самом начале. Так и есть. Если все нормально, то делаешь AcceptChanges, иначе RejectChanges. Ты не паникуй, а пробуй. Все будет нормально. Да, я понял Вашу идею; спасибо. Попробовал её – и она сработала. RejectChanges() “убрал” те “грязные” данные, вернув их к “исходному” состоянию. Что и требовалось. (были ещё некоторые проблемы, связанные с тем, что мой DataSet на самом деле не простой а сложным, с использованием Foreign Keys - головная таблица и 3 дочерние; но эти проблемы решил.) НО (вечное “но” :-) ) – мои проблемы ещё не прекратились. Итак - RejectChanges() “убрал” те “грязные” данные, вернув их к “исходному” состоянию; и я готов повторять те DB-операции (смысл же всего этого был – если DB операция failed, то сделать rollback DB-транзакции, сделать rollback DataSet-у, после чего повторить операцию). Но после RejectChanges() – о чём я сначала не подумал – все строки DataSet-а приобретут статус Unchanged. И повторные операции DbDataAdapter.Update(myDataSetObj, …) ничего в базе не вызовут – нет ни одной changed (Added, Modified) строки. А исходно (перед “самой первой” DbDataAdapter.Update(myDataSetObj, …)) все строки DataSet-а имели статус Added. Поэтому я вижу такое решение – после RejectChanges() пробежаться по всем строкам всех таблиц DataSet-а и установить им статус Added вызовом DataRow.SetAdded(). Как по-Вашему – не будет ли тут каких “подводных камней”? ... |
|||
:
Нравится:
Не нравится:
|
|||
04.06.2018, 22:18 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
KellyLynch, Все будет нормально. Ты можешь и не делать Reject, а попытаться разрешить конфликты по мере возникновения (у адаптера есть события для этого). Ты можешь просто сохранить изменения в кеше (перед сохранением в БД) и опять их накатить. Датасет, адаптер и т.д. мощный механизм, там все предусмотрено, надо просто детально разобраться. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.06.2018, 01:59 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
ViPRosKellyLynch, Все будет нормально. Ты можешь и не делать Reject, а попытаться разрешить конфликты по мере возникновения (у адаптера есть события для этого). Ты можешь просто сохранить изменения в кеше (перед сохранением в БД) и опять их накатить. Датасет, адаптер и т.д. мощный механизм, там все предусмотрено, надо просто детально разобраться. А что значит конкретно вот это - " Ты можешь просто сохранить изменения в кеше (перед сохранением в БД) и опять их накатить ." Что имелось в виду под "сохранить изменения в кеше"? Использование метода DataSet.Copy() ? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.06.2018, 12:00 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
KellyLynchЧто имелось в виду под "сохранить изменения в кеше"? Использование метода DataSet.C() ? Может еще что (GetChanges() -> Clone; Copy; вручную или еще как тебе надо и на что хватает фантазии) ... |
|||
:
Нравится:
Не нравится:
|
|||
05.06.2018, 14:28 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
ViPRosKellyLynchЧто имелось в виду под "сохранить изменения в кеше"? Использование метода DataSet.C() ? Может еще что (GetChanges() -> Clone; Copy; вручную или еще как тебе надо и на что хватает фантазии) >Может еще что (GetChanges() -> Clone; Copy; вручную или еще как тебе надо и на что хватает фантазии) Ну – я сделал так: MyClassDerivedFromDataSet myDataSetObj; <заполнение myDataSetObj данными>; …. <сохранить данные myDataSetObj в некоем myDataSetObjCopy: myDataSetObjCopy = myDataSetObj .Copy()>; <начало транзакции>; <операция DbDataAdapter.Update(myDataSetObj, …). Она заносит данные myDataSetObj в базу, а потом обновляет myDataSetObj данными, возвращёнными из базы>; If <операция выше failed> { <откатить транзакцию>; <восстановить данные myDataSetObj из myDataSetObjCopy: myDataSetObj.Clear(); myDataSetObj.Merge(myDataSetObjCopy)>; <повторно выполнить (тоже в транзакции) операцию DbDataAdapter.Update(myDataSetObj, …).> } И сработало. Это “ myDataSetObj.Clear(); myDataSetObj.Merge(myDataSetObjCopy); ” восстанавливает DataSet myDataSetObj в точности таким каким он был выше, в точке “myDataSetObjCopy = myDataSetObj .Copy()”. Но, будучи программистом опытным , я знаю – то что некий код хорошо сработал на некоем наборе данных, не является гарантией того что он так же хорошо сработает на всех возможных наборах данных. Поэтому хочу спросить – не видите ли Вы неких “подводных камней” в таком коде? Заранее благодарен за ответ. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.06.2018, 17:27 |
|
Сохранить объект DataSet, а позже восстановить его
|
|||
---|---|---|---|
#18+
KellyLynch, это точно так же делается везде, пофиг - net датасет или midas dataset или еще какая датасет ... |
|||
:
Нравится:
Не нравится:
|
|||
05.06.2018, 19:33 |
|
|
start [/forum/moderation_log.php?user_name=Hardware_nub]: |
0ms |
get settings: |
11ms |
get forum list: |
14ms |
get settings: |
10ms |
get forum list: |
14ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
116ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
51ms |
get tp. blocked users: |
2ms |
others: | 867ms |
total: | 1127ms |
0 / 0 |