/// <summary>
        /// Parses and deserializes the JsonTableSchema data stream into a DataTable object with the schema information stored in the data stream.
        /// The JsonDataSetSchemaParser class will be used to extract all the schema data in the stream into a JsonTableSchema object which then
        /// will be deserialized and used to initialize the schema of the DataTable object.
        /// </summary>
        /// <param name="streamSchema">The stream that will access the JsonTableSchema file data.</param>
        /// <returns></returns>
        public virtual DataTable DeserializeJsonTableSchema(Stream streamSchema)
        {
            JsonDataSetSchemaParser jsParser = null;

            try
            {
                jsParser = new JsonDataSetSchemaParser(streamSchema);
                JsonTableSchema tblSchema = jsParser.ParseJsonTableSchema();

                if (tblSchema == null)
                {
                    throw new InvalidDataException("Json Data Schema file invalid.  Failed to parse Json Schema file.");
                }

                DataTable dtTable = DeserializeJsonTableSchema(tblSchema);

                return(dtTable);
            }
            catch (Exception err)
            {
                ErrorHandler.ShowErrorMessage(err, "Error in DeserializeJsonTableSchema Overload 2 function of JsonDataSetSchemaSerializer class.");
                return(null);
            }
            finally
            {
                if (jsParser != null)
                {
                    jsParser.Dispose();
                }
            }
        }
        /// <summary>
        /// Serializes the schema of a DataTable to a Tiferix JsonTableSchema stream.  The function will utilize the JsonDataWriter object to extract all
        /// data from the DataTable and write it the appropriate format into the Tiferix.JsonTableSchema data stream.   All .Net DataTable objects will
        /// first be extracted and serialized into JsonTableSchema objects which will then be written to the JsonTableSchema data stream.
        /// </summary>
        /// <param name="streamSchema">JsonTableSchema data stream that will be used to serialize the schema information from the DataTable.</param>
        /// <param name="dtSchema">DataTable with schema to be serialized to JsonTableSchema data stream.</param>
        public virtual void SerializeTableSchema(Stream streamSchema, DataTable dtSchema)
        {
            try
            {
                JsonTableSchema tblSchema  = SerializeTableSchema(dtSchema);
                JsonDataWriter  jwrtSchema = new JsonDataWriter(streamSchema);

                SerializeTableSchema(jwrtSchema, tblSchema);
            }
            catch (Exception err)
            {
                ErrorHandler.ShowErrorMessage(err, "Error in SerializeTableSchema Overload 2 function of JsonDataSetSchemaSerializer class.");
            }
        }
        /// <summary>
        /// Serializes the schema of a DataSet into to a Tiferix JsonDataSetSchema object which can then be stored in a JsonDataSetSchema file.
        /// This version of the function will also be used internally to serialize a DataSet into a JsonDataSetSchema object before writing the schema
        /// information to a data stream or file on disk.
        /// </summary>
        /// <param name="dsSchema">DataSet with schema to be serialized to JsonDataSetSchema object.</param>
        /// <returns></returns>
        public virtual JsonDataSetSchema SerializeDataSetSchema(DataSet dsSchema)
        {
            try
            {
                JsonDataSetSchema dataSchema = new Data.JsonDataSetSchema();
                dataSchema.DataSetName = dsSchema.DataSetName;

                foreach (DataTable dtSchema in dsSchema.Tables)
                {
                    JsonTableSchema tblSchema = SerializeTableSchema(dtSchema);
                    dataSchema.Tables.Add(tblSchema);
                }//next dtSchema

                return(dataSchema);
            }
            catch (Exception err)
            {
                ErrorHandler.ShowErrorMessage(err, "Error in SerializeDataSetSchema Overload 1 function of JsonDataSetSchemaSerializer class.");
                return(null);
            }
        }
        /// <summary>
        /// An internal function that will use a JsonDataWriter object to serialize the data stored in a JsonTableSchema object to a JsonDataSetSchema
        /// data stream or file.  The JsonTableSchema object will have been previously loaded before the function is called and the JsonDataWriter
        /// will be positioned at the next table schema record in the data stream.
        /// </summary>
        /// <param name="jwrtSchema">JsonDataWriter object used for serializing the schema information of the DataTable to the JsonDataSetSchema
        /// data stream.</param>
        /// <param name="tblSchema">The JsonTableSchema object containing all the schema information of a DataTable to serialize to the JsonDataSetSchema
        /// data stream.</param>
        protected virtual void SerializeTableSchema(JsonDataWriter jwrtSchema, JsonTableSchema tblSchema)
        {
            try
            {
                //Writes opening '{' object bracket of either Tables schema array (of DataSet Schema file) or of the entire table schema file.
                jwrtSchema.WriteBeginObject();

                //"Table": "Table Name",
                jwrtSchema.WritePropDataValue("Table", tblSchema.TableName, true);

                //"Columns": [
                jwrtSchema.WritePropertyName("Columns");
                jwrtSchema.WriteBeginArray(true);

                //Loops through each column of the table schema and serializes the data to the stream.
                for (int iColIndex = 0; iColIndex < tblSchema.Columns.Count; iColIndex++)
                {
                    JsonColumnSchema colSchema = tblSchema.Columns[iColIndex];

                    //Write opening '{' object bracket for the column schema.
                    jwrtSchema.WriteBeginObject();

                    jwrtSchema.WritePropDataValue("ColumnName", colSchema.ColumnName, true);
                    jwrtSchema.WritePropDataValue("DataType", JsonDataUtils.ConvertToJsonDataType(colSchema.DataType), true);
                    jwrtSchema.WritePropDataValue("PrimaryKey", colSchema.PrimaryKey, true);
                    jwrtSchema.WritePropDataValue("Unique", colSchema.Unique, true);
                    jwrtSchema.WritePropDataValue("MaxLength", colSchema.MaxLength, true);
                    jwrtSchema.WritePropDataValue("AllowDBNull", colSchema.AllowDBNull, true);
                    jwrtSchema.WritePropDataValue("AutoIncrement", colSchema.AutoIncrement, true);
                    jwrtSchema.WritePropDataValue("AutoIncrementSeed", colSchema.AutoIncrementSeed, true);
                    jwrtSchema.WritePropDataValue("AutoIncrementStep", colSchema.AutoIncrementStep, true);
                    jwrtSchema.WritePropDataValue("Caption", colSchema.Caption, true);
                    jwrtSchema.WritePropDataValue("DateTimeMode", colSchema.DateTimeMode.ToString(), true);

                    if (colSchema.DefaultValue != null)
                    {
                        jwrtSchema.WritePropDataValue("DefaultValue", colSchema.DefaultValue.ToString(), true);
                    }
                    else
                    {
                        jwrtSchema.WritePropDataNullValue("DefaultValue", true);
                    }

                    jwrtSchema.WritePropDataValue("ReadOnly", colSchema.ReadOnly);

                    //Write closing '}' object bracket for the column schema.
                    jwrtSchema.WriteEndObject();

                    if (iColIndex < tblSchema.Columns.Count - 1)
                    {
                        //Writes comma field delimiter after the column end object to separate each column record.
                        jwrtSchema.WriteFieldDelimiter();
                    }
                    else
                    {
                        //The final column record will have a closing object bracket without a comma.
                        jwrtSchema.WriteNewLine();
                    }
                }//next iColIndex

                //Writes closing ']' of columns array.
                jwrtSchema.WriteEndArray();

                //Writes closing '}' object bracket of either Tables schema array (of DataSet Schema file) or of the entire table schema file.
                jwrtSchema.WriteEndObject();
            }
            catch (Exception err)
            {
                ErrorHandler.ShowErrorMessage(err, "Error in SerializeTableSchema Overload 2 function of JsonDataSetSchemaSerializer class.");
            }
        }
        /// <summary>
        /// An internal function that will deserialize the schema information contained in the JsonTableSchema passed to the function into an ADO.Net
        /// DataTable object which will then be returned by the function.  The JsonTableSchema object should have been previously loaded from the
        /// JsonDataSetSchema file before calling this function.  The function will properly convert, map and load all the appropriate columns and
        /// table settings of the DataTable with the schema information stored in the JsonTableSchema object.
        /// </summary>
        /// <param name="jsonTblSchema">JsonTableSchema object containing the schema information to deserialize to a DataTable.</param>
        /// <returns></returns>
        protected virtual DataTable DeserializeJsonTableSchema(JsonTableSchema jsonTblSchema)
        {
            try
            {
                DataTable         dtTable           = new DataTable(jsonTblSchema.TableName);
                List <DataColumn> lstPrimaryKeyCols = new List <DataColumn>();

                foreach (JsonColumnSchema jsonColSchema in jsonTblSchema.Columns)
                {
                    DataColumn column = new DataColumn();
                    column.ColumnName = jsonColSchema.ColumnName;
                    column.DataType   = jsonColSchema.DataType;
                    column.Unique     = jsonColSchema.Unique;

                    if (column.DataType == typeof(string) && jsonColSchema.MaxLength > 0)
                    {
                        column.MaxLength = jsonColSchema.MaxLength;
                    }

                    column.AllowDBNull       = jsonColSchema.AllowDBNull;
                    column.AutoIncrement     = jsonColSchema.AutoIncrement;
                    column.AutoIncrementSeed = jsonColSchema.AutoIncrementSeed;

                    if (jsonColSchema.AutoIncrementStep > 0)
                    {
                        column.AutoIncrementStep = jsonColSchema.AutoIncrementStep;
                    }

                    if (jsonColSchema.Caption != "")
                    {
                        column.Caption = jsonColSchema.Caption;
                    }

                    if (jsonColSchema.DataType == typeof(DateTime))
                    {
                        column.DateTimeMode = jsonColSchema.DateTimeMode;
                    }

                    if (jsonColSchema.DefaultValue != null)
                    {
                        column.DefaultValue = jsonColSchema.DefaultValue;
                    }

                    column.Expression = jsonColSchema.Expression;
                    column.ReadOnly   = jsonColSchema.ReadOnly;

                    if (jsonColSchema.PrimaryKey)
                    {
                        lstPrimaryKeyCols.Add(column);
                    }

                    dtTable.Columns.Add(column);
                }//next jsonColSchema

                if (lstPrimaryKeyCols.Count > 0)
                {
                    dtTable.PrimaryKey = lstPrimaryKeyCols.ToArray();
                }

                return(dtTable);
            }
            catch (Exception err)
            {
                ErrorHandler.ShowErrorMessage(err, "Error in DeserializeJsonTableSchema Overload 1 function of JsonDataSetSchemaSerializer class.");
                return(null);
            }
        }