.NET (CF) DataRow 如何自发地将所有值设置为 DBNull?

发布于 2024-12-11 06:47:29 字数 777 浏览 0 评论 0原文

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

我们发现,DataRow 的值经常会无缘无故地设置为 DBNull。更重要的是,当数据再次持久化时,主数据表的单行将被写入空数据。

例如,我们期望看到:

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

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

<MyDataSet>
<MyTypedDataRow />
...

这应该是不可能的。

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

当我尝试在调试器中导致这种情况发生时,由于表的限制,我的所有努力都会遇到错误。

有谁对这种情况如何发生有任何想法吗?

感谢您的关注。


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

I'm working with .NET DataSets in the Compact Framework. A single DataSet contains four or five tables with light data-usage (on the order of a few rows each). The primary data table (upon which all the foreign key constraints are based) contains a single row. The DataSet is persisted to disk as an XML file (using DataSet.WriteXML).

What we are finding is that, every so often, the DataRow's values all get set to DBNull for no apparent reason. What's more, when the data gets persisted again, the primary data table's single row gets written with no data.

For example, we would expect to see:

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

where "data1" and "data2" are non-nullable columns. Instead, we are rarely getting:

<MyDataSet>
<MyTypedDataRow />
...

which should be impossible.

Our environment does use multi-threading, but access to the DataSet is heavily thread-guarded.

When I attempt to cause this to happen in a debugger, all of my efforts are met with errors due to the table's constraints.

Does anyone have any thoughts on how this could be happening?

Thanks for looking.


EDIT: One thing I didn't mention which may be a contributing factor. This is a strongly-typed DataSet that was made using a Visual Studio designer, but has undergone significant manual modification after creation (don't blame me; it was before my time). Obviously, this could have a bunch of unanticipated side-effects... but I can't see how this issue could be made to happen even if we tried.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风筝在阴天搁浅。 2024-12-18 06:47:29

这确实很奇怪,我想可能还会发生其他事情。

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

这是一个适用于 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);
  }


}

This is certainly bizaare, and I'd imagine something else is likely going on.

To help you test, I'd suggest wiring up some of the event handlers that you can check.

Here is a test class you might be able to use that works for WM5 and CF 2.0.

See what's happening whenever your data is lost.

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);
  }


}
神妖 2024-12-18 06:47:29

我对这个问题有了更多的了解,我认为这会解决我的问题。

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

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

有趣的是,“WriteXML”方法在这种状态下不会抛出异常。即使它违反了所有限制,也可以以这种方式保存文件。

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

I have found out a little more about this problem, that I think will solve my issue.

I created a simple test-app that contains a designer-built strongly-typed DataSet. The application spawns three threads at start-up. Two modify the values in the same column, then read in the value, and repeat ad infintum. The third thread saves the DataSet to disk continually.

Eventually (within the span of several seconds to a minute), the threads bung up the DataSet, so that it throws an exception with the text: "DataTable internal index is corrupted: 5". If I keep swallowing these exceptions, eventually I come to an "InvalidCastException", where the data cannot be read from the row because it is DBNull. When that happens, I can see the entire row is DBNull, even primary keys.

Funny thing about it is that the "WriteXML" method does not throw an exception in this state; the file can be saved this way, even though it violates all constraints.

In my actual application, I think that my thread-guarding is not sufficient around this area. I don't know if this is a bug internal to ADO.NET, or just an argument for good thread-guarding around ADO.NET objects. Either way, it's an extremely annoying problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文