我正在使用Compact Framework中的.NET DataSet。单个DataSet包含四个或五个具有轻量数据用量的表(每个表的行数为几行)。主数据表(所有外键约束所基于的)包含单个行。 DataSet作为XML文件持久保存到磁盘(使用DataSet.WriteXML)。
我们发现,每隔一段时间,DataRow的值都会因为没有明显原因而被设置为DBNull。更重要的是,当数据再次持久化时,主数据表的单行将被写入而没有数据。
例如,我们希望看到:
<MyDataSet>
<MyTypedDataRow id="1" data1="data" data2="more data" />
...
其中“data1”和“data2”是不可为空的列。相反,我们很少得到:
<MyDataSet>
<MyTypedDataRow />
...
这应该是不可能的。
我们的环境确实使用多线程,但对DataSet的访问受到严格的线程保护。
当我试图在调试器中发生这种情况时,由于表的约束,我的所有努力都会遇到错误。
有没有人对如何发生这种情况有任何想法?
感谢您的光临。
答案 0 :(得分:0)
这当然是讽刺的,我想其他事情可能正在发生。
为了帮助您进行测试,我建议您联系一些可以检查的事件处理程序。
这是一个你可以使用的测试类,适用于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);
}
}
答案 1 :(得分:0)
我已经发现了一些关于这个问题的更多信息,我认为这将解决我的问题。
我创建了一个简单的测试应用程序,其中包含一个设计器构建的强类型DataSet。该应用程序在启动时产生三个线程。两个修改同一列中的值,然后读入值,并重复ad infintum。第三个线程不断地将DataSet保存到磁盘。
最终(在几秒到一分钟的范围内),线程会打开DataSet,因此它会引发文本异常:&#34; DataTable内部索引已损坏:5&#34;。如果我继续吞下这些异常,最终我会遇到一个&#34; InvalidCastException&#34;,其中无法从行中读取数据,因为它是DBNull。当发生这种情况时,我可以看到整行是DBNull,甚至是主键。
有趣的是,&#34; WriteXML&#34;方法不在此状态下抛出异常;文件可以这种方式保存,即使它违反了所有约束条件。
在我的实际应用中,我认为我的防线在这个领域是不够的。我不知道这是否是ADO.NET内部的错误,或者只是围绕ADO.NET对象进行良好的线程保护的论据。无论哪种方式,这都是一个非常烦人的问题。