Introduction
When you use TableAdapters in C#, VS generates INSERT
, SELECT
, and UPDATE
etc. commands for you. Other commands can be added by going into the DataSet Designer and adding commands via the Add SQL Wizard. Sometimes, however, you need additional SQL commands that contain a complete list of all the fields in the DataSet
. You would also like these lists to be automatically updated whenever a change is made to the database.
The code presented here does this by using functions in the Designer code to generate such strings.
Background
I actually developed these functions because I needed to INSERT
rows into a database and get the value of the Identity column on the fly as I tab through a DataGridView
adding new rows.
Note that this has only been developed for simple functions, but the basics are generally applicable for other applications.
Description
The file GenerateSQL.cs contains the code for a static class GenerateSQL
, which has the following functions:
public static string BuildAllFieldsSQL ( DataTable table )
Returns a list of all the columns in the DataTable
in SQL format which can be used in a SELECT
command etc. E.g.: CustomerID, CustomerName, ....
public static string BuildInsertSQL ( DataTable table )
Returns an INSERT
command with an optional SELECT CAST
statement to get the SCOPE_IDENTITY
if required. E.g.: INSERT INTO tableName ( CustomerName,...) VALUES (@CustomerName,...)
; SELECT CAST(scope_identity() AS int )
. (Note that in this example, CustomerID is an Identity so it isn't included in the string.)
public static SqlCommand CreateInsertCommand ( DataRow row )
Given a DataRow
, creates an instance of SqlCommand
to insert the data into the DataSet
.
public static object InsertDataRow ( DataRow row, string connectionString )
Given the DataRow
and a connection string, creates the SqlCommand
as above and executes it, returning the identity of the record.
For example, if the Dataset Sesigner has defined a row like:
QfrsDataSet.MembersRow row;
I can insert it into the database, getting the identity with the statement:
int id = (int) GenSQL.GenerateSQL.InsertDataRow ( row, connectionString );
Here is the complete code:
using System;
using System.Text;
using System.Data;
using System.Data.OleDb;
using System.Data.SqlClient;
namespace GenSQL
{
public static class GenerateSQL
{
public static string BuildAllFieldsSQL ( DataTable table )
{
string sql = "";
foreach ( DataColumn column in table.Columns )
{
if ( sql.Length > 0 )
sql += ", ";
sql += column.ColumnName;
}
return sql;
}
public static string BuildInsertSQL ( DataTable table )
{
StringBuilder sql = new StringBuilder ( "INSERT INTO " + table.TableName + " (" );
StringBuilder values = new StringBuilder ( "VALUES (" );
bool bFirst = true;
bool bIdentity = false;
string identityType = null;
foreach ( DataColumn column in table.Columns )
{
if ( column.AutoIncrement )
{
bIdentity = true;
switch ( column.DataType.Name )
{
case "Int16":
identityType = "smallint";
break;
case "SByte":
identityType = "tinyint";
break;
case "Int64":
identityType = "bigint";
break;
case "Decimal":
identityType = "decimal";
break;
default:
identityType = "int";
break;
}
}
else
{
if ( bFirst )
bFirst = false;
else
{
sql.Append ( ", " );
values.Append ( ", " );
}
sql.Append ( column.ColumnName );
values.Append ( "@" );
values.Append ( column.ColumnName );
}
}
sql.Append ( ") " );
sql.Append ( values.ToString () );
sql.Append ( ")" );
if ( bIdentity )
{
sql.Append ( "; SELECT CAST(scope_identity() AS " );
sql.Append ( identityType );
sql.Append ( ")" );
}
return sql.ToString (); ;
}
public static void InsertParameter ( SqlCommand command,
string parameterName,
string sourceColumn,
object value )
{
SqlParameter parameter = new SqlParameter ( parameterName, value );
parameter.Direction = ParameterDirection.Input;
parameter.ParameterName = parameterName;
parameter.SourceColumn = sourceColumn;
parameter.SourceVersion = DataRowVersion.Current;
command.Parameters.Add ( parameter );
}
public static SqlCommand CreateInsertCommand ( DataRow row )
{
DataTable table = row.Table;
string sql = BuildInsertSQL ( table );
SqlCommand command = new SqlCommand ( sql );
command.CommandType = System.Data.CommandType.Text;
foreach ( DataColumn column in table.Columns )
{
if ( !column.AutoIncrement )
{
string parameterName = "@" + column.ColumnName;
InsertParameter ( command, parameterName,
column.ColumnName,
row [ column.ColumnName ] );
}
}
return command;
}
public static object InsertDataRow ( DataRow row, string connectionString )
{
SqlCommand command = CreateInsertCommand ( row );
using ( SqlConnection connection = new SqlConnection ( connectionString ) )
{
command.Connection = connection;
command.CommandType = System.Data.CommandType.Text;
connection.Open ();
return command.ExecuteScalar ();
}
}
}
}
Using the Code
Just include the source file in your program and call the functions. The (extremely basic) sample program uses the Northwind code files, but does not connect to it.