[ Team LiB ]
Recipe 10.15 Creating aTableintheDatabasefromaDataTableSchema
Problem
You need to create a tableinadatabasefrom an existing DataTable schema.
Solution
Use the CreateTableFromSchema( ) method shown in this solution.
The sample code contains one event handler and two methods:
Button.Click
Creates aDataTable containing theschemafromthe Orders tableinthe Northwind
sample database. The method CreateTableFromSchema( ) inthe sample code is
called to create atablein the databasefrom this schema.
CreateTableFromSchema( )
This method creates aschemainthedatabase for theschema of theDataTable
argument. The method builds a DDL statement fromtheschema information and
executes it against the data source specified by the connection string argument to
create the table.
N
etType2SqlType( )
This method is called by the CreateTableFromSchemaMethod( ) to map .NET data
types to SQL Server types when building the DDL statement.
The C# code is shown in Example 10-15
.
Example 10-15. File: CreateDatabaseTableFromDataTableSchemaForm.cs
// Namespaces, variables, and constants
using System;
using System.Configuration;
using System.Windows.Forms;
using System.Text;
using System.Data;
using System.Data.SqlClient;
// . . .
private void goButton_Click(object sender, System.EventArgs e)
{
// Fill atable with the Orders table schema.
String sqlText = "SELECT * FROM [Orders]";
SqlDataAdapter da = new SqlDataAdapter(sqlText,
ConfigurationSettings.AppSettings["Sql_ConnectString"]);
DataTable dt = new DataTable("Orders");
da.FillSchema(dt, SchemaType.Source);
CreateTableFromSchema(dt,
ConfigurationSettings.AppSettings["Sql_ConnectString"]);
MessageBox.Show("Table " + TABLENAME + " created.",
"Create DataTablefrom schema.",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void CreateTableFromSchema(DataTable dt, String connectionString)
{
// Drop the new table if it is already there.
StringBuilder sqlCmd = new StringBuilder(
"if exists (SELECT * FROM dbo.sysobjects WHERE id = " +
"object_id('[" + TABLENAME + "]') " +
"AND OBJECTPROPERTY(id, 'IsUserTable') = 1)" +
Environment.NewLine +
"DROP TABLE " + TABLENAME + ";" + Environment.NewLine +
Environment.NewLine);
// Start building a command string to create the table.
sqlCmd.Append("CREATE TABLE [" + TABLENAME + "] (" +
Environment.NewLine);
// Iterate over the column collection inthe source table.
foreach(DataColumn col in dt.Columns)
{
// Add the column.
sqlCmd.Append("[" + col.ColumnName + "] ");
// Map the source column type to a SQL Server type.
sqlCmd.Append(NetType2SqlType(col.DataType.ToString( ),
col.MaxLength) + " ");
// Add identity information.
if(col.AutoIncrement)
sqlCmd.Append("IDENTITY ");
// Add AllowNull information.
sqlCmd.Append((col.AllowDBNull ? "" : "NOT ") + "NULL," +
Environment.NewLine);
}
sqlCmd.Remove(sqlCmd.Length - (Environment.NewLine.Length + 1), 1);
sqlCmd.Append(") ON [PRIMARY];" + Environment.NewLine +
Environment.NewLine);
// Add the primary key to the table, if it exists.
if(dt.PrimaryKey != null)
{
sqlCmd.Append("ALTER TABLE " + TABLENAME +
" WITH NOCHECK ADD " + Environment.NewLine);
sqlCmd.Append("CONSTRAINT [PK_" + TABLENAME +
"] PRIMARY KEY CLUSTERED (" + Environment.NewLine);
// Add the columns to the primary key.
foreach(DataColumn col in dt.PrimaryKey)
{
sqlCmd.Append("[" + col.ColumnName + "]," +
Environment.NewLine);
}
sqlCmd.Remove(sqlCmd.Length -
(Environment.NewLine.Length + 1), 1);
sqlCmd.Append(") ON [PRIMARY];" + Environment.NewLine +
Environment.NewLine);
}
sqlTextBox.Text = sqlCmd.ToString( );
// Create and execute the command to create the new table.
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(sqlCmd.ToString( ), conn);
conn.Open( );
cmd.ExecuteNonQuery( );
conn.Close( );
}
private String NetType2SqlType(String netType, int maxLength)
{
String sqlType = "";
// Map the .NET type to the data source type.
// This is not perfect because mappings are not always one-to-one.
switch(netType)
{
case "System.Boolean":
sqlType = "[bit]";
break;
case "System.Byte":
sqlType = "[tinyint]";
break;
case "System.Int16":
sqlType = "[smallint]";
break;
case "System.Int32":
sqlType = "[int]";
break;
case "System.Int64":
sqlType = "[bigint]";
break;
case "System.Byte[]":
sqlType = "[binary]";
break;
case "System.Char[]":
sqlType = "[nchar] (" + maxLength + ")";
break;
case "System.String":
if(maxLength == 0x3FFFFFFF)
sqlType = "[ntext]";
else
sqlType = "[nvarchar] (" + maxLength + ")";
break;
case "System.Single":
sqlType = "[real]";
break;
case "System.Double":
sqlType = "[float]";
break;
case "System.Decimal":
sqlType = "[decimal]";
break;
case "System.DateTime":
sqlType = "[datetime]";
break;
case "System.Guid":
sqlType = "[uniqueidentifier]";
break;
case "System.Object":
sqlType = "[sql_variant]";
break;
}
return sqlType;
}
Discussion
The solution dynamically constructs a Data Definition Language (DDL) statement to
create atableina SQL Server databasefromtheschema of a DataTable. The complete
statement that is generated is shown in Example 10-16
.
Example 10-16. DDL generated to create databasetablefromDataTableschema
if exists
(SELECT * FROM dbo.sysobjects WHERE id = object_id('[TBL1015]') AND
OBJECTPROPERTY(id, 'IsUserTable') = 1)
DROP TABLE TBL1015;
CREATE TABLE [TBL1015] (
[OrderID] [int] IDENTITY NOT NULL,
[CustomerID] [nvarchar] (5) NULL,
[EmployeeID] [int] NULL,
[OrderDate] [datetime] NULL,
[RequiredDate] [datetime] NULL,
[ShippedDate] [datetime] NULL,
[ShipVia] [int] NULL,
[Freight] [decimal] NULL,
[ShipName] [nvarchar] (40) NULL,
[ShipAddress] [nvarchar] (60) NULL,
[ShipCity] [nvarchar] (15) NULL,
[ShipRegion] [nvarchar] (15) NULL,
[ShipPostalCode] [nvarchar] (10) NULL,
[ShipCountry] [nvarchar] (15) NULL
) ON [PRIMARY];
ALTER TABLE TBL1015 WITH NOCHECK ADD
CONSTRAINT [PK_TBL1015] PRIMARY KEY CLUSTERED (
[OrderID]
) ON [PRIMARY];
The first command—the DROP statement—is not strictly required and is included here
so that the example does not crash if it has been run previously. It might be more
appropriate in your situation to check if thetable already exists inthedatabase and if it
does, abort execution since your table might contain important data. If that is the case,
return the results of the EXISTS query to the calling application and use that to control
whether the new table is created.
The second DDL command uses the CREATE TABLE statement to create the tablein
the database. The code iterates over the collection of the columns intheDataTable
schema to retrieve the name and the maximum length of the column and whether the
column is an identity column or allows null values. A method is called to map the .NET
data types of theDataTable to SQL Server data types. This method does not work
perfectly because there is not a one-to-one mapping between .NET data types and SQL
Server data types. Make the mapping decisions based on the requirements of your
application. The mapping method also adds the field length for the DDL column
description for string-type columns. For more information about mapping SQL Server
data types to .NET Framework data types, see Recipe 2.8
.
The third DDL command creates the primary key constraint on the newly constructed
table. While single-column primary keys can easily be added to the CREATE TABLE
command, the easiest way to handle compound keys is by using an ALTER TABLE
statement with an ADD CONSTRAINT statement and PRIMARY KEY argument.
Iterate over the collection of columns exposed by the PrimaryKey property of thetable to
add the columns to the command.
If you have a number of tables ina DataSet that you want to create ina database, you can
iterate through the collection of DataRelation objects for the DataSet and use the ALTER
TABLE statement with the ADD CONSTRAINT command and a FOREIGN KEY
argument to add thetable relations to the database.
For more information about DDL syntax, see Microsoft SQL Server Books Online.
[ Team LiB ]
. Team LiB ]
Recipe 10.15 Creating a Table in the Database from a DataTable Schema
Problem
You need to create a table in a database from an existing DataTable.
Button.Click
Creates a DataTable containing the schema from the Orders table in the Northwind
sample database. The method CreateTableFromSchema( ) in the sample