So from time to time I've needed to work with DataSets, either to prototype something or just experiment with them and I've always found it a pain to create them. Visual Studio has a designer, but I've always found you need to connect to a database (or an Access file) to create them, which is more than I want to do when I need some quick data to play around with.
To that end, I made a little utility to allow me to define some data in a 2D array, keep a list of those, and then load them as tables into a DataSet. I realize there are likely many ways to do this, but I've found this works for me and since I've found it fairly useful, I wanted to share it in hopes that other people get some use out of it too.
The utility I've created supports both untyped data (defined as a string and loaded in as such) or typed data (types specified, loads the specified data type). It's a static, global class with methods on it to get data. The namespace is DataFactories and the class is DataFactory. The methods available are...
Expand|Select|Wrap|Line Numbers
- /// <summary>
- /// Builds the sample data from a list of table definitions.
- /// </summary>
- /// <param name="tableDefinitions">The TableDefinitions object containing the table data.</param>
- /// <param name="columnRow">The row specifying the column. Optional, defaults to 0.</param>
- /// <param name="typeRow">The row specifying the types. Optional, defaults to -1 (no types define, defaulting to string data).</param>
- /// <param name="dataSetName">The name of the data set. Optional, defaults to no name.</param>
- /// <returns>A DataSet containing the created DataTable objects.</returns>
- public static DataSet BuildDataSet(TableDefinitions tableDefinitions, int columnRow = 0, int typeRow = -1, string dataSetName = "")
- /// <summary>
- /// Builds the sample data from a list of table definitions.
- /// </summary>
- /// <param name="tableDefinitions">The list of table definitions.</param>
- /// <param name="columnRow">The row specifying the column. Optional, defaults to 0.</param>
- /// <param name="typeRow">The row specifying the types. Optional, defaults to -1 (no types define, defaulting to string data).</param>
- /// <param name="dataSetName">The name of the data set. Optional, defaults to no name.</param>
- /// <returns>A DataSet containing the created DataTable objects.</returns>
- public static DataSet BuildDataSet(List<KeyValuePair<string, object[][]>> tableDefinitions, int columnRow = 0, int typeRow = -1, string dataSetName = "")
- /// <summary>
- /// Creates a DataTable from the parameters provided.
- /// </summary>
- /// <param name="tableName">The name of the table to create.</param>
- /// <param name="rawDataTable">The definition of the table.</param>
- /// <param name="columnRow">The row number the column names can be found on (typically the first row).</param>
- /// <param name="typeRow">The row number the types can be found on. Set this to -1 if all types are to be strings.</param>
- /// <returns></returns>
- public static DataTable BuildDataTable(string tableName, object[][] rawDataTable, int columnRow = 0, int typeRow = -1)
Lets say I've got an employee table... so maybe I'll do something like this...
Expand|Select|Wrap|Line Numbers
- private static string[][] RAW_EMPLOYEES = new string[][]
- {
- new string[] { "ID", "FIRST_NAME", "LAST_NAME" },
- // ------------------------------------------
- new string[] { "1", "Gary", "Texmo" },
- new string[] { "2", "Joe", "Smith" },
- new string[] { "3", "Jane", "Doe" }
- };
Now, the DataFactory.BuildDataSet method's tableDefinitions parameter is of type List<KeyValuePair<string, object[][]>>. This allows us to set up a list of tables, providing a string name for the table, and a 2D array of data for that table. To create this table definitions parameter, we do...
Expand|Select|Wrap|Line Numbers
- List<KeyValuePair<string, object[][]>> tableDefinitions = new List<KeyValuePair<string, object[][]>>()
- {
- new KeyValuePair<string, object[][]>("EMPLOYEES", RAW_EMPLOYEES)
- };
Expand|Select|Wrap|Line Numbers
- DataSet data = DataFactory.BuildDataSet(tableDefinitions);
Expand|Select|Wrap|Line Numbers
- TableDefinitions tableDefinitions = new TableDefinitions();
- tableDefinitions.Add("EMPLOYEES", RAW_EMPLOYEES);
- DataSet data = DataFactory.BuildDataSet(tableDefinitions);
Expand|Select|Wrap|Line Numbers
- public class SampleData
- {
- private static string[][] RAW_EMPLOYEES = new string[][]
- {
- new string[] { "ID", "FIRST_NAME", "LAST_NAME" },
- // ------------------------------------------
- new string[] { "1", "Gary", "Texmo" },
- new string[] { "2", "Joe", "Smith" },
- new string[] { "3", "Jane", "Doe" }
- };
- public static DataSet GetSampleData()
- {
- TableDefinitions tableDefinitions = new TableDefinitions();
- tableDefinitions.Add("EMPLOYEES", RAW_EMPLOYEES);
- return DataFactory.BuildDataSet(tableDefinitions);
- }
- }
Expand|Select|Wrap|Line Numbers
- try
- {
- DataSet data = SampleData.GetSampleData();
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
Now, as I mentioned, I also support loading typed data so lets say we wanted the ID column in our data to be an integer data type. We'll need to change our array from string[][] to object[][], define a row of types, and then our data. The methods on the DataFactory class take a parameter that defines what row the types are located on. This defaults to -1, which signifies that types are not defined and that column data is strings.
So our modified object array, with types, would look like...
Expand|Select|Wrap|Line Numbers
- private static object[][] RAW_EMPLOYEES = new object[][]
- {
- new object[] { "ID", "FIRST_NAME", "LAST_NAME" },
- new object[] { typeof(int), typeof(string), typeof(string) },
- // ------------------------------------------
- new object[] { 1, "Gary", "Texmo" },
- new object[] { 2, "Joe", "Smith" },
- new object[] { 3, "Jane", "Doe" }
- };
Expand|Select|Wrap|Line Numbers
- return DataFactory.BuildDataSet(tableDefinitions, 0, 1);
As you need more tables, you simply create more 2D arrays and add them to the tableDefinitions object. They will all get loaded into the DataSet in the Tables property and you can access them by name (or index).
So there we go, fairly easy to define and load data sets in order to provide sample data for our programs to work with. If, later on, you get a database connection, you can simply replace your sample data sets with the results from your database queries and your program should be able to continue on.
Because I'm a big believer in source sharing, I'm not going to provide a dll for this but instead am attaching the source code for it. Please see the attachment list for DataFactory.cs.txt. Rename this to DataFactory.cs and place it in your project, or in a new project within your solution.
If you have any questions/comments, please feel free to post them.
Thanks!