【问题标题】:Serialize and Deserialize Property Based on DB Value根据 DB 值对属性进行序列化和反序列化
【发布时间】:2012-06-08 17:52:39
【问题描述】:

我有一个具有 bool 属性的简单类。此属性的“获取”逻辑执行存储过程以从数据库返回位字段。

然后我将这个类序列化并将其保存到数据库中的 XML 字段中。它保存了类和布尔属性就好了,没问题。

我似乎遇到的问题是当我反序列化这个类时。该类反序列化就好了,但是当驱动bool字段的数据已经更新时,该类似乎只识别XML中序列化的内容,并且它没有回溯数据库获取新的bool值(不执行我获取新更新位字段的过程)。

我的解决方案是向该字段添加 XmlIgnoreAttribute 属性,这样一开始就不会对其进行序列化。但我想知道是否有人注意到这一点和/或可以帮助我了解 .NET XmlSerializer 类的内部工作。

谢谢!

[XmlIgnoreAttribute]
    public bool IsUpdated
    {
        get
        {
            DataTable dtResults = mclsSQLServerTool.LoadDataTable("exec stp_RL_SEL_NameIsUpdated '" + mstrName + "'");
            bool blnIsUpdated = Convert.ToBoolean(dtResults.Rows[0]["RU_bitIsUpdated"]);

            return blnIsUpdated;

        }
    }

【问题讨论】:

  • 我有点困惑。我认为(尚未检查) XmlSerializer 会忽略仅获取的简单值(不是列表)。这是您的实际代码吗?您预计会发生什么?
  • 我希望它执行 proc 并从数据库中获取最新值。而且我相信您对 XmlSerializer 和 get-only 值是正确的。上面的代码是我添加 XmlIgnoreAttribute 的最新代码;我曾经有一个简单的设置块{}
  • 为什么要这样做?反序列化器对 getter 并不是很感兴趣(列表等除外)——即使它确实运行了(它不应该运行),因为它不会在任何地方存储任何东西...... 你怎么知道?我>
  • 我不认为这是故意的,它只是这样做的方式。直到我们开始使用这个 DLL 并注意到这个属性的问题,所以我们打开代码并注意到这一点并修改了代码。当我们调试时,数据库总是返回一个结果,而不是反序列化对象返回的结果,尽管有 SQL 调用。所以我只是发布这个问题来尝试弄清楚 XmlSerializer 的内部工作原理。

标签: c# .net serialization xmlserializer


【解决方案1】:

恕我直言,这是对属性的滥用。属性后面应该有很少或没有代码。如果此代码曾经在客户端-服务器应用程序中使用过,您可能会从客户端进行数据库调用。我建议将其更改为方法调用。如果要序列化结果,请将“Convert.ToBoolean”的结果存储在属性中。现在对于属性值是什么有点清楚了。

这样的……

public bool IsUpdated { get; private set; }

public bool IsDataUpdated()
{ 
     DataTable dtResults = mclsSQLServerTool.LoadDataTable("exec stp_RL_SEL_NameIsUpdated '" + mstrName + "'"); 
     IsUpdated = Convert.ToBoolean(dtResults.Rows[0]["RU_bitIsUpdated"]); 

     return IsUpdated; 
} 

【讨论】:

  • 是的,我同意,对于这种类型的属性(或缺少),方法调用将是一个更好的计划
【解决方案2】:

这里首先要注意的是[XmlIgnore]是多余的; XmlSerializer 对只获取属性(列表除外)不感兴趣,因为它知道它不能反序列化它们。例如:

public class SomeType
{
    public string Foo { get; set; }
    public string Bar { get { Console.WriteLine("get_Bar"); return "abc"; } }

    static void Main()
    {
        var ser = new XmlSerializer(typeof (SomeType));
        ser.Serialize(Console.Out, new SomeType { Foo = "def" });
    }
}

输出(减去命名空间别名等):

<SomeType>
  <Foo>def</Foo>
</SomeType>

(注意 Bar 没有被调用)

对于反序列化,过程(对于简单值,而不是列表)很简单:当在传入的 xml 流中找到值时,将它们解析为成员,并分配它们 - 即 xml-deserializer 基本上是一个美化的 switch 语句基于传入的 xml 节点。

它将从不随机调用“集合”,除非数据在传入的 xml 中(并且属性是读/写);当它执行时,它期望分配一个值

您的场景中有趣的是,您的“get”不会在任何地方分配值 - 没有缓存。所以实际上,XmlSerializer 不接触它并不重要 - 每次您访问 IsUpdated 时它都会进行查询。就我个人而言,我怀疑这是一个错误,并可能导致激进且不可预测的数据查询。

许多序列化器支持序列化回调的概念,这将允许您在序列化结束时执行一些代码;但是,XmlSerializer 支持这一点。所以这不是一个选择。

目前还不是很清楚你想要实现什么,但我只是在某个时候调用一个方法。

【讨论】:

  • 感谢马克的回复。我所追求的是更好地理解序列化程序在这种情况下是如何工作的。我用的不多,尤其是这样,所以我一直在寻找任何信息来解释我看到的结果(谷歌搜索这个特定的问题很薄:))我认为方法调用可能是对这段代码进行很好的更改。
  • @BrianG behaviour 很简单:它序列化任何可以读写的公开内容;然后它扭转了这一点。它既不序列化也不反序列化你的属性,因为它不是读+写的。
  • 忽略空白集块(set{})编码不好,序列化这个属性没用,有没有办法可以想到反序列化类后立即访问IsUpdated属性会返回我是序列化值而不是 get 方法中代码的结果(在我的情况下是 SQL proc 结果)?因为是我看到的行为。再次感谢!
  • @BrianG,什么序列化值XmlSerializer 下的 get-only 属性不序列化
  • 再一次,曾经有一个空白的设置方法(set {})所以它正在被序列化。
猜你喜欢
  • 1970-01-01
  • 2018-10-31
  • 1970-01-01
  • 1970-01-01
  • 2021-05-22
  • 2016-05-31
  • 2012-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多