Форум программистов, компьютерный форум, киберфорум
C#: Базы данных, ADO.NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.92/13: Рейтинг темы: голосов - 13, средняя оценка - 4.92
0 / 0 / 0
Регистрация: 21.12.2010
Сообщений: 31
1

Сериализация/десериализация Xml, как сделать чтобы изменения вступили в силу

16.04.2012, 00:56. Показов 2404. Ответов 14
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Возникла проблема: сохраняю датасет в xml файл-успешно сохранен, изменяю бд, считываю этот файл, изменения успешно нейтрализованы, получаю базу данных на момент сериализации. Закрываю приложение, запускаю вновь-изменений нет, при этом ds.HasChanges()==true
код:
C#
1
2
3
4
5
  private void сериализоватьВBinaryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FileStream fs = new FileStream("12.xml", FileMode.CreateNew);
            ds.WriteXml(fs);
        }
C#
1
2
3
4
5
6
7
8
9
 private void найтиБазуToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FileStream fs = new FileStream("12.xml", FileMode.Open);
            ds.Clear();
            ds.ReadXml(fs);
            if (ds.HasChanges()) MessageBox.Show("sdfd");
            ds.AcceptChanges();
 
        }
Подскажите как сделать чтобы изменения реально вступили в силу, ведь как я понимаю ds.AcceptChanges(); мало для этого?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.04.2012, 00:56
Ответы с готовыми решениями:

Сериализация/Десериализация списка объектов в XML
имеется базовый класс Figure using System; using System.Collections.Generic; using System.Linq;...

Как сделать, чтобы изменения из dataGridView сохранялись в БД
Приветствую, подскажите новичку в такой проблемме. Есть таблица в бд, на форме создаю грид указываю...

Сериализация / десериализация
доброе время суток=) такое задание - отправить объект класса с приложения клиента на сервер ...

Сериализация и десериализация
Доброго вечера. Возникло странное непонимание принципов сериализации. Дело в том, что я не встречал...

14
16 / 16 / 6
Регистрация: 27.06.2010
Сообщений: 48
16.04.2012, 09:32 2
Если ds это объект типа DataSet и если я правильно понял проблему, то:
Загружая набор данных из файла в DataSet, вы лишь загружаете их в оперативную память. Выполняя метод ds.AcceptChanges(), вы не выполняете запись в базу данных, а лишь расставляете в оперативной памяти флаги RowState для каждой строки DataSet.
Чтобы таким образом полностью восстановить БД из XML-файла, нужно выполнять удаление/запись данных в БД. Способов много - поищите на форуме.
0
0 / 0 / 0
Регистрация: 21.12.2010
Сообщений: 31
16.04.2012, 14:56  [ТС] 3
а вы не поделитесь ссылкой? А то у меня опыта мало, не получается найти ничего. Мне же просто нужно считанный датасет слить с существвующим?
0
16 / 16 / 6
Регистрация: 27.06.2010
Сообщений: 48
17.04.2012, 12:23 4
Давайте тогда начнём с начала... Что Вы хотите сделать?
0
0 / 0 / 0
Регистрация: 21.12.2010
Сообщений: 31
17.04.2012, 12:32  [ТС] 5
Давайте. Я хочу мой
C#
1
DataSet ds
в котором у меня хранится 6 таблиц и 6 представлений (некоторые представления основаны на нескольких таблицах если это важно) , сереализовать в Xml. В первом сообщении я привел код который для этого использую и все работает, ds мой нормально сериализуется в Xml. Дальше я так же приведенными в первом сообщении функциями пытаюсь десеарелизовать его, опять же это делается одной функцией и проблем вроде нет. Перед тем как десериализовать я делаю изменения в одной из таблиц (удаляю строку) и сохраняю изменения. Потом чищу мой ds, десериализую и получаю что моя удаленная строка вновь вывелась, но когда перезапускаю приложения удаленной строки нет, я делаю вывод что изменения не сохранились. Вопрос: как их сохранить и нужнно ли при этомь учитывать структуры таблиц и есть простой подход полного восстановления?
0
16 / 16 / 6
Регистрация: 27.06.2010
Сообщений: 48
17.04.2012, 13:32 6
Вот это не понял:
Цитата Сообщение от hax32 Посмотреть сообщение
Перед тем как десериализовать я делаю изменения в одной из таблиц (удаляю строку) и сохраняю изменения.
Что значит "сохраняю изменения"? В Базу данных, в XML или что-то ещё делаете?

И что происходит при запуске приложения? Считывание из БД или из XML-файла?
0
0 / 0 / 0
Регистрация: 21.12.2010
Сообщений: 31
17.04.2012, 14:28  [ТС] 7
Сохраняю изменения в таблице которая в базе данных на сервере.
При запуске приложения читаю с базы данных на сервере в датасет ds все таблицы и представления.

Цитата Сообщение от hax32
"Перед тем как десериализовать я делаю изменения в одной из таблиц (удаляю строку) и сохраняю изменения."
Это значит, что я удалил или изменил строку, зафиксировал изменения в базе данных на серевере, потом считываю сериализованный датасет ds, в котором эта строка еще не удалена/изменена и в датагриде вижу что изменения действительно откатились.

Как мне сохранить то что я вижу в датагриде?

Добавлено через 45 секунд
сохраннить на сервере в бд
0
16 / 16 / 6
Регистрация: 27.06.2010
Сообщений: 48
17.04.2012, 14:47 8
Итак, всё стало на свои места...
Восстановим ход событий:
1)загрузились данные из бд в DataSet(в память)
2)сохранили данные в XML-файл
3)Удалили строку в DataSet(в памяти).
4)Зафиксировали изменение в БД.
5)Очистили DataSet и загрузили данные из XML-файла в память.
6)Методом AcceptChanges() поставили флаги что все строки в DataSet не изменялись.
Естественно ДатаГрид показывает что удалённая строка есть. Естественно в БД её нет-мы же её туда не записывали...

Чтобы что-то внятное ответить на вопрос "Как мне сохранить в БД то что я вижу в датагриде?" хотелось бы знать как вы выполняли удаление/запись в БД до этого. Просто способов действительно много, а не хотелось бы идти самым длинным путём...
0
0 / 0 / 0
Регистрация: 21.12.2010
Сообщений: 31
17.04.2012, 19:56  [ТС] 9
Итак, очень хорошо вы все сформулировали, этот тоже надо уметь)) именно такая проблема и стоит передо мной. Единственное хотелось бы сделать упор на то что я перед десериализацией очищаю полностью датасет ds, а датагридов с соответсвующими им представлениями у меня 6, поэтому нужно фиксировать все изменния сразу.
Теперь по поводу как я сохраняю/удаляю/изменяю

Ищу изменения датасета:
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
 public static void SaveData(ref DataSet changesDataSet)
        {
            DataSet addedDataSet = changesDataSet.GetChanges(DataRowState.Added);
            if (addedDataSet != null)//были добавления
            {
                authorDataAdapter.SelectCommand.Connection = cs1;
                authorDataAdapter.Update(addedDataSet.Tables["View_author"]);
                changesDataSet.Merge(addedDataSet);//объединяет данный датасет с указанным
            }
            DataSet modifiedDataSet = changesDataSet.GetChanges(DataRowState.Modified);
            if (modifiedDataSet != null)//были изменения
            {
                authorDataAdapter.SelectCommand.Connection = cs1;
                authorDataAdapter.Update(modifiedDataSet.Tables["View_author"]);
                changesDataSet.Merge(modifiedDataSet);
            }
            DataSet deletedDataSet = changesDataSet.GetChanges(DataRowState.Deleted);
            if (deletedDataSet != null)//были удаления
            {
                authorDataAdapter.SelectCommand.Connection = cs1;
                authorDataAdapter.Update(deletedDataSet.Tables["View_author"]);
                changesDataSet.Merge(deletedDataSet);
            }
        }
Дабавляю новую запись по алгоритму:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
            string name;
            string surname;
            name = textBox1.Text;
            surname = textBox2.Text;
            //DataTable table = authorTrackerDataSet.Tables["View_author"];
            if (currentRow == null)
            {
                currentRow = authorTrackerDataSet.Tables["View_author"].NewRow();//authorTrackerDataSet.Tables["Author"].NewRow();
                currentRow["Имя"] = name;
                currentRow["Фамилия"] = surname;
                authorTrackerDataSet.Tables["View_author"].Rows.Add(currentRow);
                DialogResult = DialogResult.OK;
            }
Ну и теперь добавление, удаление, изменение
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
64
65
66
67
68
69
  private void button1_Click(object sender, EventArgs e)//add author
        {
            Add_Author add = new Add_Author(ds);
            DialogResult dr = add.ShowDialog();
            if (dr == DialogResult.OK)
            {
                //ds.Tables["View_author"].AcceptChanges();
            }
        }
 
        private void button2_Click(object sender, EventArgs e)//modify
        {
            DataRow curRow;
            try
            {
                object id = view_authorDataGridView.CurrentRow.Cells[2].Value;
                curRow = ds.Tables["View_author"].Rows.Find(id);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            Add_Author ob = new Add_Author(ds, curRow);
            ob.ShowDialog();
        }
 
        private void button3_Click(object sender, EventArgs e)//delete au
        {
            DialogResult result = MessageBox.Show("Are u sure?", "Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (result == DialogResult.Yes)
            {
                object id = view_authorDataGridView.CurrentRow.Cells[2].Value;
                DataRow curRow = ds.Tables["View_author"].Rows.Find(id);
                curRow.Delete();
            }
        }
 
        private void button4_Click(object sender, EventArgs e)//save
        {
            string sql = "SELECT * FROM View_author";
            SqlDataAdapter dataAdapter = new SqlDataAdapter(sql, cs);
            //dataAdapter.Fill(ds.Tables["View_author"]);
            if (!ds.HasChanges())
            {
                MessageBox.Show("There are no changes to save", "Save Changes");
            }
            else
            {
                try
                {
                    DataSet changesDataSet = ds.GetChanges();
 
                    AuthorDAC.SaveData(ref changesDataSet);
                    ds.Merge(changesDataSet);
                    ds.Tables["View_author"].AcceptChanges();
                    ds.Tables["View_author"].Clear();
                    dataAdapter.Fill(ds.Tables["View_author"]);
                   
                   ds.AcceptChanges();
 
                    MessageBox.Show("Data Saved!");
                }
                catch (SqlException ex)
                {
                    MessageBox.Show("Data not Saved" + ex.Message, "Save Changes");
                }
            }
        }
Фуух, ну вроде все. Вот я дал основные алгоритмы. Теперь можете мне помочь корректно сохранить считанный датасет в базу а не только во временное отображения датагрида????
0
16 / 16 / 6
Регистрация: 27.06.2010
Сообщений: 48
18.04.2012, 10:45 10
Получается Вам нужен DataSet с правильно расставленными RowState.
Можно так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//предварительно заполним данными из БД DataSet dsFromDB
 
//загрузим данные из XML
DataSet dsFromXML = new DataSet();
dsFromXML.ReadXmlSchema( "6666666666666s.xml" );
dsFromXML.ReadXml( "6666666666666.xml" );
dsFromXML.AcceptChanges();
 
//через LINQ-выражение получим только те строки, которые есть в XML, но нет в БД
//сравнение выполняется по столбцу первичного ключа "id"
var deletedRows = dsFromXML.Tables[0].AsEnumerable().Where( r => !dsFromDB.Tables[0].AsEnumerable().Select( t => t.Field<long>( "id" ) ).Contains( r.Field<long>( "id" ) ) ).ToList<DataRow>();
 
for (int i = 0; i < deletedRows.Count(); i++)
{
    deletedRows[i].SetAdded();
    dsFromDB.Tables[0].ImportRow( deletedRows[i] );
}
В итоге имеем DataSet dsFromDB, в котором добавлены те строки, которые есть в XML, но нет в БД и они помечены как "Added". Если вы выполните сохранение в БД как выполняли его раньше (только для этого экземпляра DataSet), то строки добавятся в БД.
Но это только про удалённые строки... Добавленные и различающиеся аналогично...
А вообще самый простой способ-удалить всё нафиг из БД, пометить все строки как added и записать...
0
0 / 0 / 0
Регистрация: 21.12.2010
Сообщений: 31
18.04.2012, 15:56  [ТС] 11
уже почти клево, щас проверю код, единственное что хотел уточнить: я и хочу полностью датасет удалить и полностью загрузить, поэтому может эта задача решается еще проще?

и еще хотел уточнить для чего схему считывать и сохранять? разве ds.WriteXml(fs); недостаточно?

Добавлено через 45 минут
И еще вопрос, вот вы мне посоветовали
C#
1
2
3
4
5
6
7
8
9
10
 
//через LINQ-выражение получим только те строки, которые есть в XML, но нет в БД
//сравнение выполняется по столбцу первичного ключа "id"
var deletedRows = dsFromXML.Tables[0].AsEnumerable().Where( r => !dsFromDB.Tables[0].AsEnumerable().Select( t => t.Field<long>( "id" ) ).Contains( r.Field<long>( "id" ) ) ).ToList<DataRow>();
 
for (int i = 0; i < deletedRows.Count(); i++)
{
    deletedRows[i].SetAdded();
    dsFromDB.Tables[0].ImportRow( deletedRows[i] );
}
получается это к каждой таблице нужно применять? Их у меня 6 же и честно говоря не особо ясно что даст этот поиск в Linq
и неясно что в цикле происходит? Получается каждый найденный ряд помечаем как добавленный, потом импортируем заново в таблицу?

Неужели нету метода без этого построчного восстановления, что то типа - удалить весь датасет и считать в него новый?
0
16 / 16 / 6
Регистрация: 27.06.2010
Сообщений: 48
20.04.2012, 09:43 12
Цитата Сообщение от hax32 Посмотреть сообщение
для чего схему считывать и сохранять? разве ds.WriteXml(fs); недостаточно?
Иногда - нет. У меня в элементарном тестовом примере был косяк с типом DateTime. Если восстанавливать через ReadXML(), то столбец получается с типом String и невозможно свести таблицы cо столбцами разных типов через Merge().
Цитата Сообщение от hax32 Посмотреть сообщение
я и хочу полностью датасет удалить и полностью загрузить, поэтому может эта задача решается еще проще?
Конечно! Удаляем всё нафиг из БД, чистим DataSet, загружаем всё из XML, не делаем AcceptChanges() (все строки должны быть помеченными как Added) и сохраняем.
Цитата Сообщение от hax32 Посмотреть сообщение
получается это к каждой таблице нужно применять? Их у меня 6 же и честно говоря не особо ясно что даст этот поиск в Linq
и неясно что в цикле происходит? Получается каждый найденный ряд помечаем как добавленный, потом импортируем заново в таблицу?
В примере добавляются те строки, которых нет в БД, но есть в XML. Для этого их нужно сначала найти. Они отбираются через Linq. В цикле каждый найденный ряд помечаем как добавленный, потом импортируем заново в таблицу.
Это не лучшее решение. В данном случае оно бессмысленно если можно всё удалить и записать заново.
0
0 / 0 / 0
Регистрация: 21.12.2010
Сообщений: 31
20.04.2012, 13:07  [ТС] 13
Так вот я в первом посте приводил код - все удалить потом все считать. Как мне его доработать, чтобы он все таки решал мою проблему? Без линка и поиска добавленных строк, которых нет в бд.
0
16 / 16 / 6
Регистрация: 27.06.2010
Сообщений: 48
20.04.2012, 14:52 14
Сначала всё удаляем из БД (надеясь что всё потом сможем восстановить из XML).

Затем загружаем из XML и сохраняем:
C#
1
2
3
4
5
6
7
8
9
10
11
FileStream fs = new FileStream("12.xml", FileMode.Open);
ds.Clear();
ds.ReadXml(fs);
if (ds.HasChanges()) 
    MessageBox.Show("sdfd");
 
//это не нужно:
//ds.AcceptChanges(); 
 
//сохраняем
SaveData(ref DataSet ds);
0
0 / 0 / 0
Регистрация: 21.12.2010
Сообщений: 31
20.04.2012, 15:38  [ТС] 15
вот. Оно не работает почему то! не сохраняет. Уменя же для каждой таблицы отдельное сохранение, запечатано в класс, получается что мне нужно вызвать 6 раз SaveData ?Я так делал, все равно изменения не сохранились

Добавлено через 11 минут
У меня же для каждой таблицы отдельное сохранение, запечатано в класс, получается что мне нужно вызвать 6 раз SaveData ?Я так делал, все равно изменения не сохранились
0
20.04.2012, 15:38
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.04.2012, 15:38
Помогаю со студенческими работами здесь

Protobuf сериализация десериализация
Добрый день уважаемые форумчане. Помогите разобраться. Имеется клиент серверное приложение. Как...

Сериализация и десериализация ORM EF
Написал WF приложение которое работает с БД, решил прикрутить возможность сериализации и...

Как сделать чтобы изменения внесённые в запрос сохранились в базе данных?
Используется: - EntityFramework - 6.2.0; - MS Sql Server 2012; Таблицы: -...

Помогите плз по C#, сериализация десериализация
В одной программе сохраняю объект: saveFileDialog.Title = &quot;Сохранение теста&quot;;...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru