【问题标题】:Unexpected conversion Xml to DataSetXml 到 DataSet 的意外转换
【发布时间】:2018-12-19 15:29:16
【问题描述】:

我有一门课

[Serializable]
public class Car
{
    public Driver Driver = new Driver();
    public List<Driver> Drivers = new List<Driver>();
}

[Serializable]
public class Driver
{
    public int Id { get; set; }
}

当我尝试序列化此类的实例然后转换为 DataSet 时,我得到了一个非常奇怪的行为:

void Main()
{
    var x = new Car();
    x.Drivers.Add(new Driver { Id = 1 });
    var dataSet= AsDataSet(x);
    dataSet.Tables["Driver"].Rows.Count;//2!! and two columns: Id and Driver_Id
    dataSet.Tables["Drivers"].Rows.Count;//1    and only one column Driver_Id
}

static DataSet AsDataSet(Car ceInv)
{
    var serializer = new XmlSerializer(ceInv.GetType());
    var ms = new MemoryStream();
    serializer.Serialize(ms, ceInv);
    ms.Position = 0;
    var ds = new DataSet();
    ds.ReadXml(ms);
    return ds;
}

有人能告诉我为什么表 Drivers 是空的并且没有列 Id 吗? 不幸的是,属性 Driver 应该保持这样(遗留代码)。我只能更改属性驱动程序。 更改属性 Drivers 的名称对结果没有影响。

【问题讨论】:

  • 试图运行它,但没有Dump()的定义
  • 从用法中推断出Dump() 应该是什么样子。现在调查一下
  • 对不起,这是来自 linqpad 的功能。我会更正代码

标签: c# serialization dataset


【解决方案1】:

查看DataSet 的序列化表示,应该很明显。

<?xml version="1.0"?>
<Car xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Driver>
    <Id>0</Id>
  </Driver>
  <Drivers>
    <Driver>
      <Id>1</Id>
    </Driver>
  </Drivers>
</Car>

您希望ReadXml() 方法如何区分第一个&lt;Driver&gt; 元素和&lt;Drivers&gt; 元素中的元素?它们似乎是同一张表的一部分。

您还在您的 Car 类中使用空 Id 实例化一个新的 Driver,不确定这是否是故意的。

无论如何,我会让您的属性名称不那么含糊,以便ReadXml() 可以解决问题。例如,将Car 中的单个Driver 属性更改为PrimaryDriver 或类似属性。

我知道您说过您不能更改该属性,因此唯一的解决方案是自定义 XML 序列化程序,但这可能无法为您提供所需的 DataSet。

void Main()
{
    var x = new Car();
    x.Drivers.Add(new Driver { Id = 1 });
    var dataSet = AsDataSet(x);
    Console.WriteLine($"PrimaryDriver: {dataSet.Tables["PrimaryDriver"].Rows.Count}");
    Console.WriteLine($"Drivers: {dataSet.Tables["Drivers"].Rows.Count}");

    // Output:
    // PrimaryDriver: 1
    // Drivers: 1
}

[Serializable]
public class Car
{
    public Driver PrimaryDriver = new Driver();
    public List<Driver> Drivers = new List<Driver>();
}

[Serializable]
public class Driver
{
    public int Id { get; set; }
}

private static DataSet AsDataSet(Car ceInv)
{
    var serializer = new XmlSerializer(ceInv.GetType());
    var ms = new MemoryStream();
    serializer.Serialize(ms, ceInv);
    ms.Position = 0;
    var ds = new DataSet();
    //Console.WriteLine($"{new StreamReader(ms).ReadToEnd()}"); ms.Position = 0; // DEBUGGING
    ds.ReadXml(ms);
    return ds;
}

【讨论】:

    【解决方案2】:

    根据我在重命名 Car 类中的一个/两个属性后看到的情况,ReadXml() 似乎根据使用的类型推断架构,而不仅仅是属性。考虑以下;将Car的定义更改为

    [Serializable]
    public class Car
    {
        public Driver Someone { get; set; } = new Driver { Id = 47 }; // I did this so I could identify the rows
        public List<Driver> Dudes { get; set; } = new List<Driver>(); 
    }
    

    我最终在数据集中得到了 3 个表。某人,伙计和司机。单个属性按预期存储在为该属性命名的表中。另一方面,list 属性会创建一个以该类型命名的表,在本例中为 Driver,在您的情况下为属性 Drivers,在我的情况下为 Dudes。

    List&lt;Driver&gt; 属性的数据存储在 Driver 表中。它与以该属性命名的表之间存在关系。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-01
      • 2020-05-20
      • 1970-01-01
      • 2012-12-11
      相关资源
      最近更新 更多