Laden...

was kann alles in ein object[] gespeichert werden?

Erstellt von avlbger vor 17 Jahren Letzter Beitrag vor 17 Jahren 2.651 Views
avlbger Themenstarter:in
98 Beiträge seit 2005
vor 17 Jahren
was kann alles in ein object[] gespeichert werden?

Hallo Leute.

Ich hab grad versucht verschiedene POST-Aufrufe ( bzw. die System.Collections.Specialized.NameValueCollections die die Werte des jeweiligen Aufrufs enthalten) gemeinsam mit anderen Daten in ein object[] zu speichern.
Wenn ich es dann versuche auszulesen und als NameValueCollection caste, erhalte ich eine InvalidCastException dass ein String nicht zu NameValueCollection gecastet werden kann. Wo kommt den jetzt der String her?
Kann es sein dass eine NameValueCollection zu komplex ist um in einem object[] so einfach gespeichert zu werden?
Oder check ich wiedermal überhaupt nix ab weil ich wieder seit stunden und spät nachts vorm pc sitze??

Hier ein kleiner Auszug:


coll.Add("var1", 123); //Hier werden diverse Variablen der Collection hinzugefügt
coll.Add("var2", 345);
coll.Add("var3", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
queuetable.Rows.Add(new object[] { null, coll }); //Hier speichere ich die Collection in einer DataTable

//Später im Code lese ich hier bzw. versuche ich hier die Collection wieder auszulesen
coll = (System.Collections.Specialized.NameValueCollection)queuetable.Rows[i].ItemArray[1];
//Hier bekomme ich dann die InvalidCastException dass String nicht zu NameValueCollection gecastet werden kann. Dabei ist ja eigentlich kein String da drin...

3.728 Beiträge seit 2005
vor 17 Jahren
DataTable

Eine DataTable ist als Container für Datenbank-Resultsets gedacht. Man speichert keine object-Arrays in einer DataTable. Wenn man sowas tut, dann als BLOB (Binary Large Object). Da man flüchtige Objektreferezen innerhalb des Hauptspeichers (was object eigentlicbh ist) nicht persistieren kann, muss man die Objekte zuvor serialisieren (also ihren Inhaklt in ein Byte[] schreiben). Die DataTable serialisiert aber nicht automatisch.

Welchen Datentyp (DbType) hat die DataColumn, in die Du den Objektsalat speichern möchtest?

Wäre eine Hastable nicht besser geeigent, als eine DataTable?

Daß plötzlich ein string drin ist, kann dann vorkommen, wenn irgendwo ToString() zum Einsatz kommt. Was steht in dem string? (Vielleicht "System.Object[]")

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo avlbger,

ohne dass ich mir den Code näher angeguckt habe. Man kann alles in Object und damit auch alles in Object[] speichern. Nur muss man dann genau wissen, was man wo gespeichert hat und beim Herausholen wieder richtig casten. Wenn man einen String in myObjectArray [0] speichert, kann man später nicht (IrgendEinAndererInkompaiblerTyp)myObjectArray [0] verwenden, sondern muss (String)myObjectArray [0] verwenden.

Oder check ich wiedermal überhaupt nix ab weil ich wieder seit stunden und spät nachts vorm pc sitze??

vermutlich 🙂

herbivore

T
68 Beiträge seit 2006
vor 17 Jahren

Und wenn du was nicht direkt casten kannst aus einem object[] sonden mit der Brechstange es machen willst kannst es hauptsächlich über die Convert Klasse machen.

Natürlich sind casts eher Brechstangentechnik und Fehleranfällig. Wissen sollte man natürlich auch was man reingespeichert hat. Andere wege würd ich dir eher empfehlen.

avlbger Themenstarter:in
98 Beiträge seit 2005
vor 17 Jahren

Wäre eine Hastable nicht besser geeigent, als eine DataTable?

Und wie funtioniert das mit der Hashtable? Der Begriff sagt mir leider nicht viel aber ich werd mal googeln.
Werd mich auch übers serialisieren schlau machen..

Unter dem Umstand das ich alles was ich um Programmierung weiß durch Learning by Doing und Googlen erarbeitet habe bin ich recht stolz was ich so alles an Programmierversuchen zum laufen gebracht hab, leider stolpere ich wie hier eben oft über mangelndes Grundlagenwissen 😉

Gruß, avlbger

@herbivore Ich weiß 100% dass ich in mein object[] keinen String gespeichert hab, sondern eine NameValueCollection. Aber wenn ich das so mittels richtigem Cast wieder rausholen will, erzählt der mir was von String... ich vermute mal frech ohne Hintergrundwissen dass man so ein komplexes Ding wohl doch nicht so einfach in ein object[] packen kann.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo avlbger,

Und wie funtioniert das mit der Hashtable? Grundlegendes zu Hashtables (Dictionaries)

Ich weiß 100% dass ich in mein object[] keinen String gespeichert hab, sondern eine NameValueCollection. Aber wenn ich das so mittels richtigem Cast wieder rausholen will, erzählt der mir was von String... ich vermute mal frech ohne Hintergrundwissen dass man so ein komplexes Ding wohl doch nicht so einfach in ein object[] packen kann.

nein, sorry, völliger Quatsch. Du holst sicher was von einer anderen Stelle als von der Stelle, wo du es reingepackt hast. Die Komplexität spielt überhaupt keine Rolle. Und Objekte ändern auch nicht einfach ihren Typ. Deine Annahme ist leider vollkommen haltlos.

herbivore

avlbger Themenstarter:in
98 Beiträge seit 2005
vor 17 Jahren

Deine Annahme ist leider vollkommen haltlos.

..ist ja schon gut ... 8o war ja nur ein Versuch mein scheitern mir gegenüber zu rechtfertigen g

Du meinst also es müsste funktionieren die NameValueCollection in ein Object[] zu packen und dann später mittels Cast wieder als NameValueCollectionzur Verfügung zu haben?
Tja, dann werde ich eben meinen Code nochmal genau analysieren... und an diversen Stellen mal prüfen was jetzt wirklich gespeichert ist...

Vielen Dank für den Link, werd da auch mal stöbern.

gruß, avlbger

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo avlbger,

Du meinst also es müsste funktionieren die NameValueCollection in ein Object[] zu packen und dann später mittels Cast wieder als NameValueCollectionzur Verfügung zu haben?

ja, genau.

herbivore

avlbger Themenstarter:in
98 Beiträge seit 2005
vor 17 Jahren

Hallo herbivore,

Eventuell könnte es daran liegen dass ich das object[] danach in einer DataTable speichere? Wie Rainbird geschrieben hat ist da eine DataTable nicht so geeignet.
In der DataTable habe ich zwei Spalten eine für eine AutoIncrement Id und eine für die NameValueCollection. Die Spalte mit der Id habe ich auf int festgelegt, die Spalte für die Collection habe ich allerdings nicht explizit auf einen Datentyp festgelegt. Kann es sein dass das ganze dort dann einfach als String abgelegt wird?

Ich mein ich muss das nicht unbedingt in eine DataTable speichern ich kann dafür auch was anderes nehmen, nur war das das erste was mir eingefallen ist, da dort schon Methoden für das löschen und einfügen von zeilen vorhanden sind.

gruß, avlbger

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo avlbger,

Kann es sein dass das ganze dort dann einfach als String abgelegt wird?

halte ich für möglich, habe allerdings noch nicht so viel mit DataTables gemacht.

herbivore

T
68 Beiträge seit 2006
vor 17 Jahren

Hallo avlbger!

Also ich arbeite einiges mit DataTabels und deine Annahme

Kann es sein dass das ganze dort dann einfach als String abgelegt wird ist falsch. Grundsätzlich wird dort wie meistens alles als objects abgelegt.

Warum du jedoch strings da drin hast lässt mich eher auf die NameValueCollection tippen. Wenn du genau mal die Doku über NameValueCollection gelesen hast repräsentiert die Klasse eine Collection von assozierten String keys und String values. Daher diese mögliche Cast Exception.

Vermutlich begründung ohne Gewähr:
Warum nun queuetable.Rows_.ItemArray[1] einen string retourniert ist vermutlich eine Hintergrundzugriff über pointer mit einem impliziten cast hervorgerufen aufgrund der generischen Programmierung. Die Values einer Datatable neigen eher dazu ein String zu sein. Wenn nun ein Typ reinkommt der eignetlich darin weniger darin was veerloren hat wird der Default cast als beste passende bzw. default Klasse herangezogen. (strings) . Also wie es C# genau im Hintergrund macht weiß kaum jemand es ist nur eine vermutung weil ich zeimlich viel in native C++ gelernt habe. und eine Zuweisung eines Pointers auf ein array wäre in C++ gleichzusetzen mit einem Pointer aufs erste Element( und das wäre hier ja vom typ String)

Dein Fehler würd ich sagen ist die Beahhrlichkeit alles so umzugesalten das es in eine DataTable passt. Davon würd ich dir mal abraten, weil ein Element anzulegen wo der erste Wert immer null ist, ist nicht so gut. Ersten wenn du schon ein Object hast würde ich es nie noch zusätzlich in ein object[] pressen wenn du nicht ein Array von verschiedenen Objecten hast.

Wenn du sagst du brauchst sie nur zum speichern würde ich dir keine DataTable empfehlen. vielmehr eigene sich da eher eine Arraylist oder wie schon gesagt Hashtable. Denen kannst du ein object ohne Problem zuordnen.

mfg TiTime

avlbger Themenstarter:in
98 Beiträge seit 2005
vor 17 Jahren

Hallo Titime,

....deine Annahme ist falsch....

Ich nehme mal an ich sollte besser nix mehr annehmen 😉

Der erste Wert ist übrigens nicht null, bzw ja es wird null übergeben, aber nur weil ich vorher die betreffende Spalte in der DataTable als int und AutoIncrement definiert habe. Somit wird dort auch wenn ich null übergebe einfach die nächsthöhere int-zahl abgelegt.
Das ist aus meinem Codeauszug allerdings auch nicht ersichtlich.

Aber egal, du hast wohl recht, ich werd mich jetzt mal in die Hashtables einlesen und die möglichkeit mit ArrayList habe ich auch schon in Betracht gezogen. gruß, avlbger

avlbger Themenstarter:in
98 Beiträge seit 2005
vor 17 Jahren

Musste das jetzt einfach nochmal ausprobieren. Wie herbivore schon gesagt hat kann man die NameValueCollection problemlos in ein object[] packen und auch mit dem richtigen Cast problemlos wieder auslesen.
Sobald aber das object[] in dem Dataset war, funktioniert das nicht mehr. Es wird zwar noch angezeigt dass in dem Feld eine NameValueCollection enthalten ist, aber trotz richtigem Cast wird eine Exception geworfen.

       private void button2_Click(object sender, EventArgs e)
        {
            System.Collections.Specialized.NameValueCollection coll = new System.Collections.Specialized.NameValueCollection();
            coll.Add("key1", "123");
            coll.Add("key2", "234");
            object[] oa = new object[] { null,coll };
            MessageBox.Show(oa[1].ToString());
            System.Collections.Specialized.NameValueCollection colltest = (System.Collections.Specialized.NameValueCollection)oa[1];
            DataTable tbl = new DataTable();
            tbl.Columns.Add("id");
            tbl.Columns.Add("param");
            tbl.Columns[0].AutoIncrement = true;
            tbl.PrimaryKey = new System.Data.DataColumn[] { tbl.Columns[0] };
            tbl.Rows.Add(oa);
            MessageBox.Show(tbl.Rows[0].ItemArray[1].ToString());
            System.Collections.Specialized.NameValueCollection colltest2 = (System.Collections.Specialized.NameValueCollection)tbl.Rows[0].ItemArray[1];
        }

gruß, avlbger

B
1.529 Beiträge seit 2006
vor 17 Jahren

Wer lesen kann, ist klar im Vorteil:

.NET Framework Class Library
DataColumnCollection.Add Method (String)

Creates and adds a DataColumn object that has the specified name to the DataColumnCollection.

/// ...

Syntax
C#
public DataColumn Add ( string columnName )

/// ...

**
Remarks
By default, the DataType for the new column is string.**

Ergo:


tbl.Columns.Add("id", typeof( WhatKindOfTypeYourIDShallHave ) );
tbl.Columns.Add("param", typeof( System.Collections.Specialized.NameValueCollection ) );

avlbger Themenstarter:in
98 Beiträge seit 2005
vor 17 Jahren

Mann... die Idee mal zu Versuchen in der DataSet-Spalte den Typ auf NameValueCollection zu setzen hatte ich auch schon....aber irgendwie kams nie dazu dass ich das ausprobiert hab. grrr
Das wichtigste aber ist dass es so jetzt Tadellos funktioniert,
gruß, avlbger