2009-03-27 5 views
2

Ich habe einige Probleme mit XmlSerializer und XmlTextReader in C# beim Speichern von DataTables, die keine Daten enthalten. Ist dies ein bekanntes Problem und gibt es eine Problemumgehung? Wenn eine leere Datentabelle gespeichert wird mit XMLSerializer folgenden XML generiert:Gibt es einen Fehler in XmlTextReader beim Öffnen leerer Databases?

 <Values> 
     <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> 
      <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="Values" msdata:UseCurrentLocale="true"> 
      <xs:complexType> 
       <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element name="Values"> 
        <xs:complexType> 
        </xs:complexType> 
       </xs:element> 
       </xs:choice> 
      </xs:complexType> 
      </xs:element> 
     </xs:schema> 
     <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" /> 
     </Values> 

Wenn die XML diese enthält, wird neu geladen XMLTextReader leise ausfällt und nicht geladen Inhalt über den Punkt hinaus, an das die leere Datentabelle in die XML geschrieben wird. Dieses Problem scheint durch das Fehlen eines xs: sequence/xs: -Elementeintrags in xs: complexType verursacht zu werden. Ist das ein Fehler und wenn ja, was ist der Workaround?

Das folgende C# -Programm zeigt das Problem. Es wird Ausgabe DT3 aufgrund der Ausgabe oben beschriebenen null ist:

public class Data 
{ 
    private DataTable dt1; 
    private DataTable dt2; 
    private DataTable dt3; 

    public DataTable Dt1 
    { 
     get { return dt1; } 
     set { dt1 = value; } 
    } 

    public DataTable Dt2 
    { 
     get { return dt2; } 
     set { dt2 = value; } 
    } 

    public DataTable Dt3 
    { 
     get { return dt3; } 
     set { dt3 = value; } 
    } 

    public void TestDataTables() 
    { 
     if(dt1 == null) 
      Console.WriteLine("dt1 is null"); 
     if (dt2 == null) 
      Console.WriteLine("dt2 is null"); 
     if (dt3 == null) 
      Console.WriteLine("dt3 is null"); 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     // Create test object 
     Data data = new Data(); 
     data.Dt1 = new DataTable("Test1"); 
     data.Dt1.Columns.Add("Foo"); 
     data.Dt2 = new DataTable("Test2"); 
     // Adding the following line make serialization work as expected 
     //data.Dt2.Columns.Add("Foo"); 
     data.Dt3 = new DataTable("Test3"); 
     data.Dt3.Columns.Add("Foo"); 
     data.TestDataTables(); 

     // Save to XML 
     TextWriter filewriter = new StreamWriter("foo.xml"); 
     XmlTextWriter writer = new XmlTextWriter(filewriter); 
     writer.Formatting = Formatting.Indented; 
     XmlSerializer s1 = new XmlSerializer(typeof(Data)); 
     s1.Serialize(writer, data); 
     writer.Close(); 
     filewriter.Close(); 

     // Reload from XML 
     TextReader filereader = new StreamReader("foo.xml"); 
     XmlTextReader reader = new XmlTextReader(filereader); 
     XmlSerializer s2 = new XmlSerializer(typeof(Data)); 
     Data newData = s2.Deserialize(reader) as Data; 
     newData.TestDataTables(); 

    } 
} 
+0

Bitte poste ein kurzes, aber vollständiges Programm, das das Problem demonstriert - nur das rohe XML und den Code, der es mit XmlTextReader liest. Es ist unklar, was Sie meinen, wenn Sie über XmlTextReader sprechen und nicht "Objekte laden". –

Antwort

0

(nach der Bearbeitung)

Danke für den Beispielcode. Ja, ich stimme zu, dass dies ein Fehler ist. Für Problemumgehungen ... Nun, Sie könnten standardmäßig eine Spalte hinzufügen? Um die Kreuzkontamination zu vermeiden, könnten Sie ShouldSerialize* verwenden:

public bool ShouldSerializeDt1() { 
    return dt1 != null && dt1.Columns.Count > 0; 
} 
public bool ShouldSerializeDt2() { 
    return dt2 != null && dt2.Columns.Count > 0; 
} 
public bool ShouldSerializeDt3() { 
    return dt3 != null && dt3.Columns.Count > 0; 
} 

Wenigstens dann dt2, die ausgelassen wird, statt DT3.

+0

Ich habe jetzt ein Codebeispiel, das das Problem Marc zeigt. Das obige C# -Programm wird ausgeben dt3 ist null. Durch Hinzufügen einer Spalte zu dt2 können dt1, dt2 und dt3 korrekt serialisiert werden. – Bardsley

0

ich gerade diese Abfrage geschrieben haben, auf MSDN Forum:

Wie können Sie eine leere Datatable Session serialisiert? http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataset/thread/4704d53c-ca3a-4da1-8257-b2b05c2e9e32

Bevor ich ein neues Thema hier posten, dann ist dies das gleiche Problem wie Sie hier berichten, bitte? Ich bin nicht sicher, weil ich keine explizite Seialization selbst verwende, ich setze gerade ein DataSet (das eine DataTable ohne Zeilen enthält) in die Session, die außerhalb des Prozesses gespeichert/wiederhergestellt wird.

Verwandte Themen