【问题标题】:How can a .NET (CF) DataRow spontaneously set all values to DBNull?.NET (CF) DataRow 如何自发地将所有值设置为 DBNull?
【发布时间】:2011-12-11 06:16:08
【问题描述】:

我正在使用 Compact Framework 中的 .NET 数据集。一个 DataSet 包含四个或五个具有少量数据使用的表(每个表大约有几行)。主数据表(所有外键约束都基于该表)包含一行。 DataSet 以 XML 文件的形式保存到磁盘(使用 DataSet.WriteXML)。

我们发现,每隔一段时间,DataRow 的值都会无缘无故地设置为 DBNull。更重要的是,当数据再次被持久化时,主数据表的单行被写入没有数据。

例如,我们希望看到:

<MyDataSet>
<MyTypedDataRow id="1" data1="data" data2="more data" />
...

其中“data1”和“data2”是不可为空的列。相反,我们很少得到:

<MyDataSet>
<MyTypedDataRow />
...

这应该是不可能的。

我们的环境确实使用多线程,但对 DataSet 的访问受到严格的线程保护。

当我尝试在调试器中发生这种情况时,由于表的约束,我的所有努力都遇到了错误。

有人对这种情况有什么想法吗?

感谢收看。


编辑:我没有提到的一件事可能是一个促成因素。这是一个使用 Visual Studio 设计器制作的强类型数据集,但在创建后经历了重大的手动修改(不要怪我;那是在我的时代之前)。显然,这可能会产生许多意料之外的副作用......但即使我们尝试过,我也看不出这个问题是如何发生的。

【问题讨论】:

  • 您的设备是否在这些错误之间休眠?也许它……不知何故从睡梦中迷失了。 (???)
  • 不,我不认为是这样(但感谢您的建议;在这一点上,我正在寻找我没有想到的任何想法)。我们的设备连续运行,不会进入任何睡眠状态。有趣的是,我们的应用程序日志清楚地显示了数据集最后一次修改(成功)的时间,然后保存了......然后 8 秒后,当应用程序尝试访问同一行中的其他数据时报告“InvalidCastException”那是刚刚修改过的。尽管我们已经设置了线程保护,但我愿意相信这是一个线程问题......但我不知道如何。

标签: .net compact-framework strongly-typed-dataset


【解决方案1】:

我发现了更多关于这个问题的信息,我认为这会解决我的问题。

我创建了一个简单的测试应用程序,其中包含设计人员构建的强类型数据集。应用程序在启动时产生三个线程。两个修改同一列中的值,然后读入该值,然后无限重复。第三个线程不断将 DataSet 保存到磁盘。

最终(在几秒到一分钟的范围内),线程破坏了 DataSet,因此它抛出异常并显示文本:“DataTable 内部索引已损坏:5”。如果我继续吞下这些异常,最终我会遇到“InvalidCastException”,因为它是 DBNull,所以无法从行中读取数据。发生这种情况时,我可以看到整行都是 DBNull,甚至是主键。

有趣的是,“WriteXML”方法在这种状态下抛出异常;文件可以通过这种方式保存,即使它违反了所有约束。

在我的实际应用中,我认为我在这方面的线程保护是不够的。我不知道这是否是 ADO.NET 内部的错误,或者只是 ADO.NET 对象周围良好线程保护的一个论据。无论哪种方式,这都是一个非常烦人的问题。

【讨论】:

    【解决方案2】:

    这当然很奇怪,我想可能会发生其他事情。

    为了帮助您进行测试,我建议您连接一些您可以检查的事件处理程序。

    这是一个您可以使用的适用于 WM5 和 CF 2.0 的测试类。

    查看数据丢失时发生的情况。

    class TestOnly {
    
      public DataTable Table { get; set; }
    
      public TestOnly() {
        Table = new DataTable();
        Table.Disposed += new EventHandler(Table_Disposed);
        Table.ColumnChanging += new DataColumnChangeEventHandler(Table_ColumnChanging);
        Table.RowChanging += new DataRowChangeEventHandler(Table_RowChanging);
        Table.RowDeleting += new DataRowChangeEventHandler(Table_RowDeleting);
        Table.TableClearing += new DataTableClearEventHandler(Table_TableClearing);
      }
    
      bool myAct = false;
    
      void Table_TableClearing(object sender, DataTableClearEventArgs e) {
        Console.WriteLine("Table {0} clearing. {1}", e.TableName, DateTime.Now);
      }
    
      void Table_ColumnChanging(object sender, DataColumnChangeEventArgs e) {
        if (!myAct) {
          e.Row.CancelEdit();
          Console.WriteLine("Edit of {0} cancelled. {1}", e.Column.Caption, DateTime.Now);
        }
      }
    
      void Table_RowChanging(object sender, DataRowChangeEventArgs e) {
        if (!myAct) {
          e.Row.CancelEdit();
          Console.WriteLine("DataRow Action {0} cancelled. {2}", e.Action, DateTime.Now);
        }
      }
    
      void Table_RowDeleting(object sender, DataRowChangeEventArgs e) {
        if (!myAct) {
          e.Row.CancelEdit();
          Console.WriteLine("DataRow Action {0} cancelled. {2}", e.Action, DateTime.Now);
        }
      }
    
      void Table_Disposed(object sender, EventArgs e) {
        Console.WriteLine("Table Disposed at {0}.", DateTime.Now);
      }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 2014-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多