ComponentOne DataObjects for .NET
Working with ADO.NET Dataset
DataObjects for .NET (Enterprise Edition) > Features and Techniques > Working with ADO.NET Dataset

A C1DataSet component stores its data in an ADO.NET DataSet and that internal storage is accessible via the StorageDataSet property. This enables a powerful combination of DataObjects for .NET and ADO.NET in the same code, see DataObjects for .NET and ADO.NET.

You can see an example of these techniques used in code in the ADOStorage sample in the ComponentOne Samples directory. The sample project has extensive explanatory comments in the code.

This functionality allows you to access and modify the ADO.NET data set storing table data. You can use both DataObjects for .NET and ADO.NET to access the same data. Essentially, you have two views to the same data. The first view is a DataObjects for .NET data set (C1DataSet), and the second is the corresponding ADO.NET data set (StorageDataSet). If you change data in one of them and then switch to the other, it will automatically reflect the changed data.

When you fill or modify a C1DataSet, DataObjects for .NET stores table data internally in an ADO.NET data set. You can access this data set at any time through the StorageDataSet property. This ADO.NET data set contains only simple table rows. For each simple table, you will find a table with the same name in the underlying ADO.NET data set (you can also access data tables with StorageDataTable and individual columns with StorageDataColumn). Table views are not stored in this ADO.NET data set, because they do not contain data as such, their rows only contain pointers to table rows; for more information, see Structured Data Storage: Tables and Table Views.

Using the StorageDataSet property, you can work directly with the ADO.NET data set or export data from a C1DataSet to an ADO.NET data set or to XML. So, the conversion from C1DataSet to ADO.NET DataSet is easy, just use the StorageDataSet property.

Conversion from an ADO.NET data set to C1DataSet is also possible, but it can require additional work, because we also need to set up table view rows, which are not stored in the ADO.NET data set. By "conversion process" process we mean modifying the underlying ADO.NET data set, StorageDataSet.

You can modify StorageDataSet using any means available in ADO.NET, and then "synchronize" it with the C1DataSet, that is, set up table view rows pointing to the table rows. The conversion, that is, modification/synchronization process has two stages:

First, you modify StorageDataSet (fill simple tables with data or modify their data as you need), and second, you fill table views with rows that point to table rows.

Changing data in the ADO.NET data tables comprising StorageDataSet is only allowed on the first stage of this process. When the first stage ends, tables are filled with data. You must exercise caution not to modify ADO.NET table data directly except on the first stage of the modification/synchronization process (but of course you can modify it at any time through the regular DataObjects for .NET programmatic object model). DataObjects for .NET does not enforce this – it is developer's responsibility. Violating this restriction will not be detected by DataObjects for .NET and can have unpredictable consequences.

At the beginning of the second stage, all table views are cleared so you can fill them with rows (pointing to table rows). To fill a table view, use the C1DataSet.SetTableViewRows method. If you do not call C1DataSet.SetTableViewRows for a table view, it will be called automatically at the end of the second stage, with default parameters. So, if your table view contains all possible table rows, without restrictions (filters), you do not need to do anything with it on the second stage. But in many cases, such as when you used filter conditions filling C1DataSet, you need to control the collection of table rows that belong to table views. This is done using the C1DataSet.SetTableViewRows method for each such table view. You have two options: either to enumerate the rows manually (for instance, scanning the existent table rows, finding the ones that must belong to the table view, or to call GetDefaultTableViewRows that provides the full list of all existing table rows so you can filter them and then pass the filtered list to C1DataSet.SetTableViewRows.

The complete modification/synchronization process looks like this:

// start 
c1DataSet1.StorageChangeBegin()
// fill or modify tables (modify data in StorageDataSet)
...first stage...
// first stage complete, tables filled, table views are 
// undefined at this point
c1DataSet1.StorageChanged(true)
// fill table views with rows pointing to tables
// (calling SetTableViewRows())
...second stage...
// process complete, both tables and table views filled
c1DataSet1.StorageChangeEnd()
Note: For a complete example see the ADOStorage sample, which is installed with the Studio for WinForms samples.