/// <summary>
        /// Gets the table schema from table mapping.
        /// </summary>
        /// <param name="tableMapping">The table mapping.</param>
        /// <returns>DataTable.</returns>
        private static DataTable GetTableSchemaFromTableMapping(ITableMapping tableMapping)
        {
            tableMapping.Validate();

            string tableName;

            if (!string.IsNullOrWhiteSpace(tableMapping.Schema))
            {
                tableName = $"{tableMapping.Schema}.{tableMapping.TableName}";
            }
            else
            {
                tableName = tableMapping.TableName;
            }

            var dataTable = new DataTable
            {
                TableName = tableName
            };

            foreach (var columnMapping in tableMapping.ColumnMappings)
            {
                dataTable.Columns.Add(columnMapping.AsDataColumn());
            }

            return(dataTable);
        }
        /// <summary>
        /// Populates the specified data table.
        /// </summary>
        /// <param name="dataTable">The data table.</param>
        /// <param name="objects">The objects.</param>
        /// <param name="tableMapping">The table mapping.</param>
        /// <param name="enforceConstraints">If set to <c>true</c>, it enforces constraints.</param>
        private static void Populate(this DataTable dataTable, IEnumerable <object[]> objects, ITableMapping tableMapping, bool enforceConstraints = false)
        {
            if (!enforceConstraints)
            {
                dataTable.Constraints.Clear();
            }

            var internalObjects = objects.Where(item => item != null && item.Length > 0);

            foreach (var objectArray in internalObjects)
            {
                var dataRow = dataTable.NewRow();

                var columnMappings = tableMapping.ColumnMappings;

                for (var idx = 0; idx < columnMappings.Count; idx++)
                {
                    var columnMapping = columnMappings[idx];

                    var columnName = columnMapping.Name;

                    var value = objectArray[idx];

                    if (value != null)
                    {
                        if (columnMapping.Type.IsEnum)
                        {
                            dataRow[columnName] = value.GetHashCode();
                        }
                        else
                        {
                            value = Convert.ChangeType(value, columnMapping.Type);

                            dataRow[columnName] = value;
                        }
                    }
                    else
                    {
                        if (!columnMapping.AllowNull)
                        {
                            if (columnMapping.Type == typeof(string))
                            {
                                dataRow[columnName] = string.Empty;
                            }
                            else
                            {
                                dataRow[columnName] = columnMapping.DefaultValue;
                            }
                        }
                        else
                        {
                            dataRow[columnName] = DBNull.Value;
                        }
                    }
                }

                dataTable.Rows.Add(dataRow);
            }
        }
        /// <summary>
        /// Converts the objects to a strongly typed data table.
        /// </summary>
        /// <param name="objects">The objects.</param>
        /// <param name="tableMapping">The table mapping.</param>
        /// <returns>DataTable.</returns>
        /// <exception cref="ArgumentNullException">
        /// objects
        /// or
        /// tableMapping
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Objects have different lengths.
        /// or
        /// Columns
        /// </exception>
        public static DataTable AsStronglyTypedDataTable(this IEnumerable <object[]> objects, ITableMapping tableMapping)
        {
            if (objects == null)
            {
                throw new ArgumentNullException(nameof(objects));
            }

            if (tableMapping == null)
            {
                throw new ArgumentNullException(nameof(tableMapping));
            }

            if (objects.Any(x => (x?.Length).GetValueOrDefault() != tableMapping.ColumnMappings.Count))
            {
                throw new ArgumentException("Objects have different lengths.");
            }

            var dataTable = GetTableSchemaFromTableMapping(tableMapping);

            if (dataTable.Columns == null || dataTable.Columns.Count <= 0)
            {
                throw new ArgumentException(nameof(dataTable.Columns));
            }

            dataTable.Populate(objects, tableMapping);

            dataTable.AcceptChanges();

            return(dataTable);
        }