Creating a SQL Server table from a C# datatable

前端 未结 9 1053
死守一世寂寞
死守一世寂寞 2020-12-01 01:38

I have a DataTable that I manually created and loaded with data using C#.

What would be the most efficient way to create a table in SQL Server 2005 that uses the col

相关标签:
9条回答
  • 2020-12-01 02:12

    Here is some code that I have written to do just this thing for work. It has been tested and used in a production environment for script generation. It handles DBNull and primary keys properly and does not fail if there are none or only one. It is also more performant than the other suggestions here because it uses StringBuilder, Linq's Aggregate and does not call ToString() repeatedly.

    Note: If your data is coming from an external source, please make sure your code always sanitizes the input to this method or check the output of this method before blindly executing the generated script against your database.

        /// <summary>
        /// Creates a SQL script that creates a table where the columns matches that of the specified DataTable.
        /// </summary>
        public static string BuildCreateTableScript(DataTable Table)
        {
            if (!Helper.IsValidDatatable(Table, IgnoreZeroRows: true))
                return string.Empty;
    
            StringBuilder result = new StringBuilder();
            result.AppendFormat("CREATE TABLE [{1}] ({0}   ", Environment.NewLine, Table.TableName);
    
            bool FirstTime = true;
            foreach (DataColumn column in Table.Columns.OfType<DataColumn>())
            {
                if (FirstTime) FirstTime = false;
                else
                    result.Append("   ,");
    
                result.AppendFormat("[{0}] {1} {2} {3}",
                    column.ColumnName, // 0
                    GetSQLTypeAsString(column.DataType), // 1
                    column.AllowDBNull ? "NULL" : "NOT NULL", // 2
                    Environment.NewLine // 3
                );
            }
            result.AppendFormat(") ON [PRIMARY]{0}GO{0}{0}", Environment.NewLine);
    
            // Build an ALTER TABLE script that adds keys to a table that already exists.
            if (Table.PrimaryKey.Length > 0)
                result.Append(BuildKeysScript(Table));
    
            return result.ToString();
        }
    
        /// <summary>
        /// Builds an ALTER TABLE script that adds a primary or composite key to a table that already exists.
        /// </summary>
        private static string BuildKeysScript(DataTable Table)
        {
            // Already checked by public method CreateTable. Un-comment if making the method public
            // if (Helper.IsValidDatatable(Table, IgnoreZeroRows: true)) return string.Empty;
            if (Table.PrimaryKey.Length < 1) return string.Empty;
    
            StringBuilder result = new StringBuilder();
    
            if (Table.PrimaryKey.Length == 1)
                result.AppendFormat("ALTER TABLE {1}{0}   ADD PRIMARY KEY ({2}){0}GO{0}{0}", Environment.NewLine, Table.TableName, Table.PrimaryKey[0].ColumnName);
            else
            {
                List<string> compositeKeys = Table.PrimaryKey.OfType<DataColumn>().Select(dc => dc.ColumnName).ToList();
                string keyName = compositeKeys.Aggregate((a,b) => a + b);
                string keys = compositeKeys.Aggregate((a, b) => string.Format("{0}, {1}", a, b));
                result.AppendFormat("ALTER TABLE {1}{0}ADD CONSTRAINT pk_{3} PRIMARY KEY ({2}){0}GO{0}{0}", Environment.NewLine, Table.TableName, keys, keyName);
            }
    
            return result.ToString();
        }
    
        /// <summary>
        /// Returns the SQL data type equivalent, as a string for use in SQL script generation methods.
        /// </summary>
        private static string GetSQLTypeAsString(Type DataType)
        {
            switch (DataType.Name)
            {
                case "Boolean": return "[bit]";
                case "Char": return "[char]";
                case "SByte": return "[tinyint]";
                case "Int16": return "[smallint]";
                case "Int32": return "[int]";
                case "Int64": return "[bigint]";
                case "Byte": return "[tinyint] UNSIGNED";
                case "UInt16": return "[smallint] UNSIGNED";
                case "UInt32": return "[int] UNSIGNED";
                case "UInt64": return "[bigint] UNSIGNED";
                case "Single": return "[float]";
                case "Double": return "[double]";
                case "Decimal": return "[decimal]";
                case "DateTime": return "[datetime]";
                case "Guid": return "[uniqueidentifier]";
                case "Object": return "[variant]";
                case "String": return "[nvarchar](250)";
                default: return "[nvarchar](MAX)";
            }
        }
    

    An example of the generated output:

    CREATE TABLE [Order] (
       [OrderID] [bigint] UNSIGNED NOT NULL 
       ,[Description] [nvarchar](250) NULL 
       ,[Flag] [bit] NULL 
       ,[Quantity] [int] NULL 
       ,[Price] [decimal] NULL 
       ,[Customer] [nvarchar](MAX) NOT NULL 
    ) ON [PRIMARY]
    GO
    
    ALTER TABLE Order
       ADD CONSTRAINT pk_OrderIDCustomer PRIMARY KEY (OrderID, Customer)
    GO
    

    Everything is included except for Helper.IsValidDatatable(), but you get the idea. This should at least be replaced by a null check and probably check against zero DataColumns. In fact, if your curious, this code comes from a larger (but still under 1000 lines) open-source C# class library of mine that facilitates moving data from a C# class object to a DataTable, then to SQL scripts and back again. It also contains several helper data access methods for more succinct code. I call it EntityJustworks and it is where the body of the method IsValidDatatable() lives as well (In the Helper.cs class file). You can access the code either via CodePlex (https://entityjustworks.codeplex.com) or view a complete listing of all the other places (GitHub, Code.MSDN, Pastebin, ect) that EntityJustworks can be acquired by visiting its blog post (http://www.csharpprogramming.tips/2015/01/entity-justworks-class-to-sql.html).

    0 讨论(0)
  • 2020-12-01 02:12

    I would just build a Create Table statement based on the DataTable and send that to Database. You can use SMO (SQL Server Managment objects) as well. Not sure what would be the fastest.

    This is definitely something that could go into a framework level class for reuse.

    The following link contains information (and code sample of a SqlTableCreator) on how to do this: Creating a new table in SQL Server from ADO.NET DataTable. You can find forks of SqlTableCreator here, here, and here.

    Hope that helps.

    0 讨论(0)
  • 2020-12-01 02:14
    public static string CreateTABLE(string tableName, DataTable table)
    {
        string sqlsc;
        sqlsc = "CREATE TABLE " + tableName + "(";
        for (int i = 0; i < table.Columns.Count; i++)
        {
            sqlsc += "\n [" + table.Columns[i].ColumnName + "] ";
            string columnType = table.Columns[i].DataType.ToString();
            switch (columnType)
            {
                case "System.Int32":
                    sqlsc += " int ";
                    break;
                case "System.Int64":
                    sqlsc += " bigint ";
                    break;
                case "System.Int16":
                    sqlsc += " smallint";
                    break;
                case "System.Byte":
                    sqlsc += " tinyint";
                    break;
                case "System.Decimal":
                    sqlsc += " decimal ";
                    break;
                case "System.DateTime":
                    sqlsc += " datetime ";
                    break;
                case "System.String":
                default:
                    sqlsc += string.Format(" nvarchar({0}) ", table.Columns[i].MaxLength == -1 ? "max" : table.Columns[i].MaxLength.ToString());
                    break;
            }
            if (table.Columns[i].AutoIncrement)
                sqlsc += " IDENTITY(" + table.Columns[i].AutoIncrementSeed.ToString() + "," + table.Columns[i].AutoIncrementStep.ToString() + ") ";
            if (!table.Columns[i].AllowDBNull)
                sqlsc += " NOT NULL ";
            sqlsc += ",";
        }
        return sqlsc.Substring(0,sqlsc.Length-1) + "\n)";
    }
    
    0 讨论(0)
提交回复
热议问题