在保存不包含任何数据的DataTable时,我在c#中使用XmlSerializer和XmlTextReader时遇到了一些问题。这是一个已知问题,是否有解决方法?使用XMLSerializer保存空数据表时,将生成以下XML:
<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>
当重新加载包含它的XML时,XMLTextReader会以静默方式失败,并且不会将空数据加载到XML之外的内容加载。此问题似乎是由xs:complexType中缺少xs:sequence / xs:元素条目引起的。这是一个错误,如果是的话,解决方法是什么?
以下c#程序演示了该问题。由于上述问题,它将输出dt3为空:
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 :(得分:0)
我倾向于在数据集上使用write xml方法,你可以尝试将其作为解决方法。
http://msdn.microsoft.com/en-us/library/system.data.dataset.writexml.aspx
答案 1 :(得分:0)
(编辑后)
感谢您的示例代码。是的,我同意这是一个错误。对于变通方法......好吧,您可以默认添加一列吗?为避免交叉污染,您可以使用ShouldSerialize*
:
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;
}
至少然后是dt2被省略,而不是dt3。
答案 2 :(得分:0)
我刚刚在MSDN论坛上发布了此查询:
如何将空DataTable序列化为Session? http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataset/thread/4704d53c-ca3a-4da1-8257-b2b05c2e9e32
在此处发布新主题之前,这是与您在此报道的问题相同吗? 我不确定因为我自己没有使用任何显式的Seialization,我只是将一个DataSet(包含一个没有行的DataTable)放入Session中,该会话在进程外保存/恢复。