NullReferenceException podczas deserializacji XML

0

Cześć. Mam problem z deserializacją pliku XML. Zapisywany jest (wydaje mi się) poprawnie, po otworzeniu wygląda OK. Jednak za chiny ludowe, nie mogę wczytać go w programie.
Oto klasa, która odpowiada za Zapisywanie/Wczytywanie pliku

 
class Saver
    {
        private string filesPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "folder" + Path.DirectorySeparatorChar;

        public Saver() {}

        public void save(Plik plik) {
            XmlSerializer serializer = new XmlSerializer(typeof(Plik));
            using (Stream output = File.OpenWrite(filesPath + pies.fileName))
            {
                serializer.Serialize(output, plik);
            }
        }

        public Plik load(string nazwa_pliku) {
            XmlSerializer deserializer = new XmlSerializer(typeof(Plik));

            using (Stream input = File.OpenRead(filesPath + nazwa_pliku))
            {
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.CheckCharacters = false;
                Plik lokalny_plik = (Plik)deserializer.Deserialize(XmlReader.Create(input, settings));

                return lokalny_plik;
            }
        }
    }

A tutaj klasa przeznaczona do serializacji:

[Serializable]
    public class Plik
    {
        public string fileName { get; set; }
        [XmlArray]
        public List<Typ1> lista_1 { get; set; }
        [XmlArray]
        public List<Typ2> lista_2 { get; set; }
    }
 

Błąd wyrzuca przy linijce

 
wczytany_plik = saver.load(this.pobierzNazwePliku());

A sama nazwa pliku pobierana jest z bazy danych (MySql):

private string pobierzNazwePliku()
        {
            string query = @"SELECT * FROM `nazwa_bazy`.`tabela` WHERE `id`='" + index +"'";
            MySqlDataReader reader;
            connection.Open();

            string nazwa_pliku = "";

            try
            {
                using (MySqlCommand command = new MySqlCommand(query, connection))
                {
                    reader = command.ExecuteReader();
                    DataTable table = new DataTable();
                    table.Load(reader);

                    if (reader.HasRows)
                    {
                        foreach (DataRow row in table.Rows)
                        {
                            nazwa_pliku = row["nazwa_pliku"].ToString();
                        }
                    }
                }
            }
            catch (MySqlException)
            {
                MessageBox.Show("Błąd logowania do bazy danych", "Błąd");
            }
            finally
            {
                connection.Close();
            }

            return nazwa_pliku;
0

Teoretycznie tutaj duzo rzeczy moze byc nullem, na przyklad ten "saver". Proponowalbym zaczepic sie tam debuggerem i po prostu zobaczyc:)

0

Chyba znalazłem problem. Metoda pobierzNazwePliku() - nie pobiera jej, zwracając pusty string. Czyli albo literówka przy query, albo sama logika funkcji jest pokićkana.

Wiem już też, że mimo, iż rekord do którego chcę się odwołać istnieje w bazie danych, sam plik również, to jednak DataTable jest pusta.

0

A w ogole sprawdzales to query czy w ogole dziala? Jakos dziwnie wyglada ;p I albo jestem slepy, albo nie widze, gdzie np wypelniasz ten parametr

Druga sprawa to to, ze skoro wykorzystujesz tylko jedna kolumne (nazwa_pliku) to raczej nie musisz zaciagac wszystkich danych:)

0

Gdzie w funkcji load dostajesz wyjątek?

0
FakeAccount napisał(a):

A w ogole sprawdzales to query czy w ogole dziala? Jakos dziwnie wyglada ;p

Moje doświadczenie z bazami jest bardzo ubogie, więc niewątpliwie coś poplątałem. Query teoretycznie działa - skopiowałem ją z innej formatki, która pobiera mi wszystkie rekordy z tabeli, i w miarę umiejętności przerobiłem.

FakeAccount napisał(a):

I albo jestem slepy, albo nie widze, gdzie np wypelniasz ten parametr

 
private void dataGridView1_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            index = dataGridView1.Rows[e.RowIndex].Cells["columnID"].Value.ToString();

            using (var form = new DrugaFormatka(index))
            {
                var result = form.ShowDialog();
                if (result == DialogResult.OK) this.loadDataGridView();
            }
        }

Pobierz z DataGridView, klikając element, który odpowiada za konkretny rekord. I część danych przechowuję właśnie w pliku. Nazwa pliku z kolei Tworzona jest na podstawie ID (w bazie) i kilku danych personalnych. Stąd potrzeba wykorzystania go :)

1

Postaw sobie break pointy w miescach gdzie ten index sie ustawia i na tej linijce, gdzie wyskakuje exception. Odpal program. Jak zatrzyma sie na breakpoincie z ustawianiem indeksu to przejdz debuggerem dalej (domyslnie f10 w VS), sprawdz jaka wartosc zwrocil. Potem sprawdz na bazie czy doklandie to quesry z dokladnie taka wartoscia cos zwroci. Nastepnie (jesli zwroci) pusc debugger dalej az sie zatrzyma na kolejnym breakpoincie i sprawdz co tam jest nullem ;)

Btw, to

`nazwa_bazy`.`tabela`

bym jednak sprawdzil ;p

0

Opiszę to trochę po łopatowemu, ale mam nadzieję, że zrozumiale. W zakładce "local" w debuggerze, mam zmienną DataTable o nazwie table, o wartości null. Po wykonaniu query, wartość zmienia się na {tabela}, ale cały czas właściwość table.Rows.Count, zwraca 0.

Czyli dobrze rozumiem, że query wykonało się w takim razie po części prawidłowo, bo z tabelą się połączyło, tylko nie pobrało wartości, tak?

1

Raczej tak. Dla pewnosci skopiuj to query, ktore masz w zmiennej "query" - tez powinno być w okienku locals - i pusc je na bazie i zobacz czy wtedy cos zwroci

0

Nie było mnie jakiś czas, niemniej problem z kodem aktualny :P

FakeAccount napisał(a):

Dla pewnosci skopiuj to query, ktore masz w zmiennej "query" - tez powinno być w okienku locals - i pusc je na bazie i zobacz czy wtedy cos zwroci

query jest prawidłowe, w konsoli baza wyrzuca rekord. Zrezygnowałem jednak z tego sposobu i okazało się, że przyczyna zdaje się tkwić gdzieś w konstruktorze(?), lub metodzie tworzącej obiekt formatkę.

W Form1 mam DataGridView, gdzie poprzez zdarzenie CellContentDoubleClick(object sender, DataGridViewCellEventArgs e) pobieram indeks, który przekazuję do tej drugiej formatki i w MessageBox wyświetlam komunikat z wartościami, by upewnić się, że faktycznie zostały poprawnie wprowadzone:

 private void dataGridView1_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            index = dataGridView1.Rows[e.RowIndex].Cells["columnID"].Value.ToString();
            nazwa_pliku = dataGridView1.Rows[e.RowIndex].Cells["columnPlik"].Value.ToString();

            MessageBox.Show("ID: " + index + " Nazwa pliku: " + nazwa_pliku);

            using (var form = new Form2(index, nazwa_pliku))
            {
                var result = form.ShowDialog();
                if (result == DialogResult.OK) this.loadDataGridView(); // metoda, która aktualizuje mi tabelę
            }
        }

Kiedy jednak w konstruktorze tej drugiej formatki, zapisuje te wartości do lokalnych zmiennych - okazują się one być puste (wyświetlam sobie drugi messagebox, by je sprawdzić).

1 użytkowników online, w tym zalogowanych: 0, gości: 1