0

作为这个问题的背景,我想将“制作的代码”绑定DataTableaspx:GridView. 为了持久化这个表,我实现了ISerializable接口。该表显示正确,但在对行进行排序的回发中,InvalidCastExcpetion由于 row.ItemArray 中的元素从 type 更改为 type double,因此引发了 a string

这是课堂。注意:两个构造函数,一个用于初始化DataTable,一个用于在反序列化过程中构建表:

   [global::System.Serializable()]
   [global::System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")]
    public partial class HeatMapVisualisationDataTable : DataTable, System.Runtime.Serialization.ISerializable
    {
        #region members
        public double _valueMin { get; private set; }
        public double _valueMax { get; private set; }
        #endregion membders

        public HeatMapVisualisationDataTable(XemlExperimentHeatMapDataTable data)
            : base("result", "http://gmd.mpimp-golm.mpg.de/HeatMap")
        {
            this.Columns.Add(new DataColumn("metabolite", typeof(Guid)));

            this.Columns.Add(new DataColumn("name", typeof(string)));

            DataColumn[] PrimaryKeyColumns = new DataColumn[1];
            PrimaryKeyColumns[0] = this.Columns["metabolite"];
            this.PrimaryKey = PrimaryKeyColumns;

            SortedDictionary<int, DataColumn> headers = new SortedDictionary<int, DataColumn>();
            foreach (var item in data.AsParallel().AsEnumerable().Select(x => x.ObservationPointId).Distinct().OrderBy(x => x))
            {
                DataColumn dc = this.Columns.Add(item.ToString(), typeof(Double));
                headers.Add(item, dc);
            }

            foreach (var item in data)
            {
                DataRow tmpRow = base.Rows.Find(item.MetaboliteId);
                if (tmpRow == null)
                {
                    tmpRow = base.Rows.Add(new object[] { item.MetaboliteId });
                    tmpRow["name"] = item.MetaboliteName;
                }
                tmpRow[headers[item.ObservationPointId]] = item.value;
            }

            this.AcceptChanges();

            _valueMax = data.AsParallel().AsUnordered().Max(x => x.value);
            _valueMin = data.AsParallel().AsUnordered().Min(x => x.value);
        }

        public HeatMapVisualisationDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext ctxt) :
            base(info, ctxt)
        {
            _valueMin = (double)info.GetValue("valueMin", typeof(double));
            _valueMax = (double)info.GetValue("valueMax", typeof(double));
        }

        public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext ctxt)
        {
            base.GetObjectData(info, ctxt);
            info.AddValue("valueMin", _valueMin);
            info.AddValue("valueMax", _valueMax);
        }
    }

正如我通过阅读SerializationInfo构造函数中的架构可以观察到的那样HeatMapVisualisationDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext ctxt),该表已正确序列化,并且就序列化的 xml 架构而言,该表是从“存储”正确的。但是,查看此构造函数中构造的基类,序列化之前类型的所有列double现在都是类型string。我究竟做错了什么?

更新 1:我还可以通过将数字数据类型从更改doublefloat或来重现此问题decimal。类型的主键列Guid被反序列化为正确的类型。

更新 2DataTable.ReadXml() :在我看来,所描述的行为是对列的 DataTypes 被 String 替换的一些问题的跟进。

谢谢,扬

4

1 回答 1

0

作为一种通过绕过 DataTable 的序列化为 XML 以及随后使用 XML 从 XML 重新创建 DataTable 的解决方案ReadXml,我使用了这篇关于 ADO.NET 对象的二进制序列化的 MSDN 文章。诀窍是将有关列名和列类型的信息存储在一些额外的信息中ArrayList,并将它们放入序列化中。在这里查看我当前的ISerializable接口实现:

public HeatMapVisualisationDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext ctxt)
    base()
{
    _valueMin = info.GetSingle("valueMin");
    _valueMax = info.GetSingle("valueMax");

    System.Collections.ArrayList colNames = (System.Collections.ArrayList)info.GetValue("colNames", typeof(System.Collections.ArrayList));
    System.Collections.ArrayList colTypes = (System.Collections.ArrayList)info.GetValue("colTypes", typeof(System.Collections.ArrayList));
    System.Collections.ArrayList dataRows = (System.Collections.ArrayList)info.GetValue("dataRows", typeof(System.Collections.ArrayList));

    // Add columns
    for (int i = 0; i < colNames.Count; i++)
    {
        DataColumn col = new DataColumn(colNames[i].ToString(), Type.GetType(colTypes[i].ToString()));
        this.Columns.Add(col);
    }

    // Add rows
    for (int i = 0; i < dataRows.Count; i++)
    {
        DataRow row = this.Rows.Add((object[])dataRows[i]);
    }

    this.AcceptChanges();
}

public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext ctxt)
{
    System.Collections.ArrayList colNames = new System.Collections.ArrayList();
    System.Collections.ArrayList colTypes = new System.Collections.ArrayList();
    System.Collections.ArrayList dataRows = new System.Collections.ArrayList();

    foreach (DataColumn col in this.Columns)
    {
        colNames.Add(col.ColumnName);
        colTypes.Add(col.DataType.FullName);
    }

    foreach (DataRow row in this.Rows)
    {
        dataRows.Add(row.ItemArray);
    }

    info.AddValue("colNames", colNames);
    info.AddValue("colTypes", colTypes);
    info.AddValue("dataRows", dataRows);
    info.AddValue("valueMin", _valueMin);
    info.AddValue("valueMax", _valueMax);
}

请注意,我不再调用 DataTableGetObjectData(...)和构造函数进行反序列化。但是,这不是我原始帖子的答案。这只是一种解决方法......所以问题是“为什么要ReadXml()更改 DataTypes?” 仍然开放!

于 2012-06-19T09:16:23.963 回答