I’ve run into a problem that has me pretty confused. I’m getting a VersionNotFoundException when trying to change the RowFilter property of a DataView. This happened in a large system that I’m working on, but I’ve been able to duplicate the behavior in a relatively small (80 lines) sample program that’s at the end of this post.
I posted a message on Microsoft’s forum, but haven’t received any helpful responses. Perhaps somebody who reads this can help me out. A Google search revealed a few similar problems (although no exact matches), but I didn’t see a small reproducible case or any kind of resolution to the problem.
Short explanation of problem:
I have a DataSet with two tables: Legislators and Authors. The Legislators table contains a list of all Legislators who can potentially be an author or coauthor on a bill. The Authors table contains a record for each Legislator who has signed onto the bill as an author or coauthor (the Authors table will contain information for one bill at a time). The DataSet enforces a relation: the LegislatorCode value in an Authors record must match a LegislatorCode that’s in the Legislators table. I use a DataView to maintain a view of the Legislators table showing only those legislators who have not signed onto the bill.
This all works on the initial load, as shown in the program below. However, if I then add an Authors record, the DataView isn’t updated to reflect the change. That is, even though there now is an Authors record for a legislator, that legislator still shows up in the DataView. So, figuring I had to trigger a refresh of the DataView, I set RowFilter to string.Empty, and then set it back to what it was. I then get an exception “System.Data.VersionNotFoundException: There is no Original data to access.”
Further testing shows that this only happens if I accept changes on the Legislators table (i.e. the parent table in the relation). It appears that the code which processes the relation is looking for the child record to have an Original version if the parent has an Original version. It seems to me that it should be looking for the Current version.
I have two questions:
- Why doesn’t the DataView update when I enter the new Authors record?
- Why do I get this exception?
Any help, especially a workaround or somebody pointing out where I’m doing something wrong, would be appreciated.
The sample program:
// C# program to illustrate unexpected behavior in DataView.RowFilter
using System;
using System.Data;
namespace dvTest
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
DataSet myds = new DataSet();
// Create the tables
DataTable tblLegislators = new DataTable("Legislators");
tblLegislators.Columns.Add("LegislatorCode");
tblLegislators.Columns.Add("DisplayName");
DataTable tblAuthors = new DataTable("Authors");
tblAuthors.Columns.Add("BillNumber");
tblAuthors.Columns.Add("LegislatorCode");
// AuthorType: P = Primary author, C = Coauthor
tblAuthors.Columns.Add("AuthorType");
// Add tables to dataset
myds.Tables.Add(tblLegislators);
myds.Tables.Add(tblAuthors);
// Add a relationship.
myds.Relations.Add(tblLegislators.Columns["LegislatorCode"],
tblAuthors.Columns["LegislatorCode"]);
// populate the legislators table
tblLegislators.Rows.Add(new object[] {"A0123", "Smith (A0123)"});
tblLegislators.Rows.Add(new object[] {"A1234", "Jones (A1234)"});
tblLegislators.Rows.Add(new object[] {"A5038", "Jackson (A5038)"});
tblLegislators.Rows.Add(new object[] {"A0191", "Morton (A0191)"});
// Populate the Authors table.
// LegislatorCode must be present in Legislators table
tblAuthors.Rows.Add(new object[] {"001", "A0123", "P"});
tblAuthors.Rows.Add(new object[] {"001", "A5038", "C"});
// Accept changes on the dataset.
myds.AcceptChanges();
// dvLegislators is a dataview that contains legislators
// that do not have a record in tblAuthors.
DataView dvLegislators = new DataView(
tblLegislators,
"Count(Child.LegislatorCode)=0",
"DisplayName",
DataViewRowState.CurrentRows);
// Show contents
ShowLegislators(dvLegislators);
// Add another coauthor
Console.WriteLine("Add Legislator 0191 as a coauthor");
tblAuthors.Rows.Add(new object[] {"001", "A0191", "C"});
// Show contents -- why is 0191 still in this DataView?
ShowLegislators(dvLegislators);
// Re-filter the DataView
dvLegislators.RowFilter = "";
try
{
// Why does this throw an exception?
dvLegislators.RowFilter = "Count(Child.LegislatorCode)=0";
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.WriteLine("Press Enter");
Console.ReadLine();
}
static void ShowLegislators(DataView dvLegislators)
{
// Display contents of dvLegislators
Console.WriteLine("dvLegislators contains:");
foreach (DataRowView drv in dvLegislators)
{
Console.WriteLine(drv["DisplayName"].ToString());
}
Console.WriteLine();
}
}
}