While starting to code for any new application, we require to write POCO (Plain Old CLR Objects) classes for our database tables as Models (if you are using any ORM for data access) and also require the stored procedures for our database tables. The process is though simple, but most of time repetitive and just like other developers I try to avoid it, so I wrote this simple Windows Forms application which helps me create database table POCO/model classes, Base repository and related repository classes for the database tables in order to use Dapper ORM framework (which I mostly use in my web applications) and basic stored procedures scripts (like insert
, update
, delete
, etc.) for the selected database tables. This saves the time and helps me to avoid writing repetitive code.
This application is primarily targeting databases designed in SQL Server.
This is how the application looks:
Let's look into the code of the application and how it works. The flow of the application can be understood by the following diagram:
As you can see from the diagram, the first event occurs when the application is started and user clicks on ‘Get Database List’ button after entering the DB server connection string. The code of that event is as follows:
private void btnGetDBList_Click(object sender, EventArgs e)
{
String conxString = txtConnectionString.Text.Trim();
using (var sqlConx = new SqlConnection(conxString))
{
sqlConx.Open();
var tblDatabases = sqlConx.GetSchema("Databases");
sqlConx.Close();
foreach (DataRow row in tblDatabases.Rows)
{
cboDatabases.Items.Add(row["database_name"]);
}
}
cboDatabases.Items.Add("Select Database");
cboDatabases.SelectedIndex = cboDatabases.Items.Count - 1;
}
As per the above source code, the application is getting the list of databases using ‘GetSchema(“Databases”)
’ method of ‘SqlConnection
’ object and then adding each item of the list to ‘Select Database
’ dropdown. As per application flow (above diagram), the next user action is to select the database from the ‘Select Database
’ drop down.
On the selection of database from dropdown application will fire ‘cboDatabases_SelectedIndexChanged
’ event to get the tables list from the database and show it in the application checkbox list like the following image.
The source code of the dropdown selected index change event is as follows:
private void cboDatabases_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
if (cboDatabases.Text.Trim() != "Select Database")
{
mSSqlDatabase = cboDatabases.Text.Trim();
string strConn = txtConnectionString.Text.Trim() + ";Initial Catalog=" + mSSqlDatabase;
SqlConnection cbConnection = null;
try
{
DataTable dtSchemaTable = new DataTable("Tables");
using (cbConnection = new SqlConnection(strConn))
{
SqlCommand cmdCommand = cbConnection.CreateCommand();
cmdCommand.CommandText = "select table_name as
Name from INFORMATION_SCHEMA.Tables where TABLE_TYPE ='BASE TABLE'";
cbConnection.Open();
dtSchemaTable.Load(cmdCommand.ExecuteReader(CommandBehavior.CloseConnection));
}
cblTableList.Items.Clear();
for (int iCount = 0; iCount < dtSchemaTable.Rows.Count; iCount++)
{
cblTableList.Items.Add(dtSchemaTable.Rows[iCount][0].ToString());
}
}
finally
{
cbConnection.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error : " + ex.Message,
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
The next action taken by the user as per application flow is to either click on ‘Generate SQL’ / ‘Generate Classes’ / ‘Generate Both SQL & Classes’ button. Let's understand the code of ‘Generate SQL’ button click event handler first given as below:
private void btnGenSQL_Click(object sender, EventArgs e)
{
try
{
GenerateSQLScripts();
MessageBox.Show("SQL file(s) created Successfully at
path mentioned in 'SQL Query Files'", "Success");
grpOutPut.Visible = true;
}
catch (Exception ex)
{
MessageBox.Show("Error : " + ex.Message,
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
The above written code uses the following methods in order to generate SQL scripts of selected tables:
private void GenerateSQLScripts()
{
string sFolderPath = CreateOutputDir(txtNamespace.Text.Trim()
!= "" ? txtNamespace.Text.Trim() : mSSqlDatabase);
var objTableNames = new ArrayList();
string sConString = txtConnectionString.Text + ";Initial Catalog=" + mSSqlDatabase;
for (int iTableCount = 0; iTableCount <
cblTableList.CheckedItems.Count; iTableCount++)
{
objTableNames.Add(cblTableList.CheckedItems[iTableCount].ToString());
}
txtQueryFilePath.Text = SqlScriptGenerator.GenerateSQLFiles
(sFolderPath, sConString, txtgrantUser.Text.Trim(),
txtSPPrefix.Text.Trim(), cbxMultipleFiles.Checked, objTableNames);
}
private string CreateOutputDir(string aSDirName)
{
string sRootDirPath = Path.GetDirectoryName
(Application.ExecutablePath) + "\\" + aSDirName;
if (!Directory.Exists(sRootDirPath)) Directory.CreateDirectory(sRootDirPath);
return sRootDirPath;
}
‘GenerateSQLScripts
’ method uses ‘CreateOutputDir
’ method to first create the folder to store the SQL scripts and then loops through each selected table of the list and generate the SQL files using ‘GenerateSQLFiles
’ method of ‘SqlScriptGenerator
’ class.
The code of ‘GenerateSQLFiles
’ method of ‘SqlScriptGenerator
’ is as follows:
public static string GenerateSQLFiles(string outputDirectory,
string connectionString, string grantLoginName,
string storedProcedurePrefix, bool createMultipleFiles, ArrayList tableNames)
{
string databaseName = "";
string sqlPath;
sqlPath = Path.Combine(outputDirectory, "SQL");
List
<Table> tableList = AppUtility.GetTableList
(connectionString, outputDirectory, tableNames, ref databaseName);
int count = 0;
if (tableList.Count > 0)
{
AppUtility.CreateSubDirectory(sqlPath, true);
CreateUserQueries(databaseName, grantLoginName, sqlPath, createMultipleFiles);
foreach (Table table in tableList)
{
CreateInsertStoredProcedure(table, grantLoginName,
storedProcedurePrefix, sqlPath, createMultipleFiles);
CreateUpdateStoredProcedure(table, grantLoginName,
storedProcedurePrefix, sqlPath, createMultipleFiles);
CreateDeleteStoredProcedure(table, grantLoginName,
storedProcedurePrefix, sqlPath, createMultipleFiles);
CreateDeleteAllByStoredProcedures(table, grantLoginName,
storedProcedurePrefix, sqlPath, createMultipleFiles);
CreateSelectStoredProcedure(table, grantLoginName,
storedProcedurePrefix, sqlPath, createMultipleFiles);
CreateSelectAllStoredProcedure(table, grantLoginName,
storedProcedurePrefix, sqlPath, createMultipleFiles);
CreateSelectAllByStoredProcedures(table, grantLoginName,
storedProcedurePrefix, sqlPath, createMultipleFiles);
count++;
}
}
return sqlPath;
}
In the above ‘GenerateSQLFiles
’ method, the application is first getting the table list of the given database using ‘GetTableList
’ and then generating the SQL script for CRUD operations of those tables by looping through each table. Apart from general Insert
, Update
, Delete
stored procedures, the application creates Select
stored procedures based on all Primary and Foreign keys using ‘CreateSelectAllByStoredProcedures
’ method, similarly it creates stored procedure to delete rows on the basis of all Primary and Foreign keys using ‘CreateDeleteAllByStoredProcedures
’ method. The code of all these methods is as follows:
internal static void CreateInsertStoredProcedure
(Table table, string grantLoginName, string storedProcedurePrefix,
string path, bool createMultipleFiles)
{
string procedureName = storedProcedurePrefix + table.Name + "Insert";
string fileName;
if (createMultipleFiles)
{
fileName = Path.Combine(path, procedureName + ".sql");
}
else
{
fileName = Path.Combine(path, "StoredProcedures.sql");
}
using (StreamWriter writer = new StreamWriter(fileName, true))
{
if (createMultipleFiles == false)
{
writer.WriteLine();
writer.WriteLine("/******************************************************************************");
writer.WriteLine("******************************************************************************/");
}
writer.WriteLine("if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[" + procedureName +
"]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)");
writer.WriteLine("\tdrop procedure [dbo].[" + procedureName + "]");
writer.WriteLine("GO");
writer.WriteLine();
writer.WriteLine("CREATE PROCEDURE [dbo].[" + procedureName + "]");
writer.WriteLine("(");
for (int i = 0; i < table.Columns.Count; i++)
{
Column column = table.Columns[i];
if (column.IsIdentity == false && column.IsRowGuidCol == false)
{
writer.Write("\t" + AppUtility.CreateParameterString(column, true));
if (i < (table.Columns.Count - 1))
{
writer.Write(",");
}
writer.WriteLine();
}
}
writer.WriteLine(")");
writer.WriteLine();
writer.WriteLine("AS");
writer.WriteLine();
writer.WriteLine("SET NOCOUNT ON");
writer.WriteLine();
foreach (Column column in table.Columns)
{
if (column.IsRowGuidCol)
{
writer.WriteLine("SET @" + column.Name + " = NEWID()");
writer.WriteLine();
break;
}
}
writer.WriteLine("INSERT INTO [" + table.Name + "]");
writer.WriteLine("(");
for (int i = 0; i < table.Columns.Count; i++)
{
Column column = table.Columns[i];
if (column.IsIdentity == false)
{
if (i < (table.Columns.Count - 1))
{
writer.WriteLine("\t[" + column.Name + "],");
}
else
{
writer.WriteLine("\t[" + column.Name + "]");
}
}
}
writer.WriteLine(")");
writer.WriteLine("VALUES");
writer.WriteLine("(");
for (int i = 0; i < table.Columns.Count; i++)
{
Column column = table.Columns[i];
if (column.IsIdentity == false)
{
if (i < (table.Columns.Count - 1)) { writer.WriteLine
("\t@" + column.Name + ","); } else
{ writer.WriteLine("\t@" + column.Name); } } }
writer.WriteLine(")"); {
writer.WriteLine();
writer.WriteLine("GRANT EXECUTE ON [dbo].[" + procedureName + "]
TO [" + grantLoginName + "]");
writer.WriteLine("GO");
}
}
}
internal static void CreateUpdateStoredProcedure(Table table,
string grantLoginName, string storedProcedurePrefix, string path, bool createMultipleFiles)
{
if (table.PrimaryKeys.Count > 0 && table.Columns.Count
!= table.PrimaryKeys.Count && table.Columns.Count != table.ForeignKeys.Count)
{
string procedureName = storedProcedurePrefix + table.Name + "Update";
string fileName;
if (createMultipleFiles)
{
fileName = Path.Combine(path, procedureName + ".sql");
}
else
{
fileName = Path.Combine(path, "StoredProcedures.sql");
}
using (StreamWriter writer = new StreamWriter(fileName, true))
{
if (createMultipleFiles == false)
{
writer.WriteLine();
writer.WriteLine("/******************************************************************************");
writer.WriteLine("******************************************************************************/");
}
writer.WriteLine("if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[" + procedureName + "]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)");
writer.WriteLine("\tdrop procedure [dbo].[" + procedureName + "]");
writer.WriteLine("GO");
writer.WriteLine();
writer.WriteLine("CREATE PROCEDURE [dbo].[" + procedureName + "]");
writer.WriteLine("(");
for (int i = 0; i < table.Columns.Count; i++)
{
Column column = table.Columns[i];
if (i == 0)
{
}
if (i < (table.Columns.Count - 1))
{
writer.WriteLine("\t" +
AppUtility.CreateParameterString(column, false) + ",");
}
else
{
writer.WriteLine("\t" +
AppUtility.CreateParameterString(column, false));
}
}
writer.WriteLine(")");
writer.WriteLine();
writer.WriteLine("AS");
writer.WriteLine();
writer.WriteLine("SET NOCOUNT ON");
writer.WriteLine();
writer.WriteLine("UPDATE [" + table.Name + "]");
writer.Write("SET");
bool firstLine = true;
for (int i = 0; i < table.Columns.Count; i++)
{
var column = table.Columns[i];
if (table.PrimaryKeys.Contains(column) == false)
{
if (firstLine)
{
writer.Write(" ");
firstLine = false;
}
else
{
writer.Write("\t");
}
writer.Write("[" + column.Name + "] = @" + column.Name);
if (i < (table.Columns.Count - 1))
{
writer.Write(",");
}
writer.WriteLine();
}
}
writer.Write("WHERE");
for (int i = 0; i < table.PrimaryKeys.Count; i++)
{ Column column = table.PrimaryKeys[i]; if (i == 0)
{ writer.Write(" [" + column.Name + "] = @" +
column.Name); } else { writer.Write("\tAND [" +
column.Name + "] = @" + column.Name); } }
writer.WriteLine(); writer.WriteLine("GO"); {
writer.WriteLine();
writer.WriteLine("GRANT EXECUTE ON [dbo].[" +
procedureName + "] TO [" + grantLoginName + "]");
writer.WriteLine("GO");
}
}
}
}
internal static void CreateDeleteStoredProcedure(Table table,
string grantLoginName, string storedProcedurePrefix, string path, bool createMultipleFiles)
{
if (table.PrimaryKeys.Count > 0)
{
string procedureName = storedProcedurePrefix + table.Name + "Delete";
string fileName;
if (createMultipleFiles)
{
fileName = Path.Combine(path, procedureName + ".sql");
}
else
{
fileName = Path.Combine(path, "StoredProcedures.sql");
}
using (StreamWriter writer = new StreamWriter(fileName, true))
{
if (createMultipleFiles == false)
{
writer.WriteLine();
writer.WriteLine("/******************************************************************************");
writer.WriteLine("******************************************************************************/");
}
writer.WriteLine("if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[" + procedureName + "]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)");
writer.WriteLine("\tdrop procedure [dbo].[" + procedureName + "]");
writer.WriteLine("GO");
writer.WriteLine();
writer.WriteLine("CREATE PROCEDURE [dbo].[" + procedureName + "]");
writer.WriteLine("(");
for (int i = 0; i < table.PrimaryKeys.Count; i++)
{
Column column = table.PrimaryKeys[i];
if (i < (table.PrimaryKeys.Count - 1))
{
writer.WriteLine("\t" +
AppUtility.CreateParameterString(column, false) + ",");
}
else
{
writer.WriteLine("\t" + AppUtility.CreateParameterString(column, false));
}
}
writer.WriteLine(")");
writer.WriteLine();
writer.WriteLine("AS");
writer.WriteLine();
writer.WriteLine("SET NOCOUNT ON");
writer.WriteLine();
writer.WriteLine("DELETE FROM [" + table.Name + "]");
writer.Write("WHERE");
for (int i = 0; i < table.PrimaryKeys.Count; i++)
{ Column column = table.PrimaryKeys[i]; if (i == 0)
{ writer.WriteLine(" [" + column.Name + "] = @" +
column.Name); } else { writer.WriteLine("\tAND [" +
column.Name + "] = @" + column.Name); } }
writer.WriteLine("GO"); {
writer.WriteLine();
writer.WriteLine("GRANT EXECUTE ON [dbo].[" +
procedureName + "] TO [" + grantLoginName + "]");
writer.WriteLine("GO");
}
}
}
}
internal static void CreateDeleteAllByStoredProcedures(Table table,
string grantLoginName, string storedProcedurePrefix, string path, bool createMultipleFiles)
{
foreach (List<Column> compositeKeyList in table.ForeignKeys.Values)
{
StringBuilder stringBuilder = new StringBuilder(255);
stringBuilder.Append(storedProcedurePrefix + table.Name + "DeleteAllBy");
for (int i = 0; i < compositeKeyList.Count; i++)
{ Column column = compositeKeyList[i]; if (i > 0)
{
stringBuilder.Append("_" + AppUtility.FormatPascal(column.Name));
}
else
{
stringBuilder.Append(AppUtility.FormatPascal(column.Name));
}
}
string procedureName = stringBuilder.ToString();
string fileName;
if (createMultipleFiles)
{
fileName = Path.Combine(path, procedureName + ".sql");
}
else
{
fileName = Path.Combine(path, "StoredProcedures.sql");
}
using (StreamWriter writer = new StreamWriter(fileName, true))
{
if (createMultipleFiles == false)
{
writer.WriteLine();
writer.WriteLine("/******************************************************************************");
writer.WriteLine("******************************************************************************/");
}
writer.WriteLine("if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[" + procedureName + "]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)");
writer.WriteLine("\tdrop procedure [dbo].[" + procedureName + "]");
writer.WriteLine("GO");
writer.WriteLine();
writer.WriteLine("CREATE PROCEDURE [dbo].[" + procedureName + "]");
writer.WriteLine("(");
for (int i = 0; i < compositeKeyList.Count; i++)
{
Column column = compositeKeyList[i];
if (i < (compositeKeyList.Count - 1))
{
writer.WriteLine
("\t" + AppUtility.CreateParameterString(column, false) + ",");
}
else
{
writer.WriteLine("\t" + AppUtility.CreateParameterString(column, false));
}
}
writer.WriteLine(")");
writer.WriteLine();
writer.WriteLine("AS");
writer.WriteLine();
writer.WriteLine("SET NOCOUNT ON");
writer.WriteLine();
writer.WriteLine("DELETE FROM [" + table.Name + "]");
writer.Write("WHERE");
for (int i = 0; i < compositeKeyList.Count; i++)
{ Column column = compositeKeyList[i]; if (i == 0)
{ writer.WriteLine(" [" + column.Name + "] = @" +
column.Name); } else { writer.WriteLine("\tAND [" +
column.Name + "] = @" + column.Name); } }
writer.WriteLine("GO"); {
writer.WriteLine();
writer.WriteLine("GRANT EXECUTE ON [dbo].[" +
procedureName + "] TO [" + grantLoginName + "]");
writer.WriteLine("GO");
}
}
}
}
internal static void CreateSelectStoredProcedure(Table table,
string grantLoginName, string storedProcedurePrefix, string path, bool createMultipleFiles)
{
if (table.PrimaryKeys.Count > 0 && table.ForeignKeys.Count != table.Columns.Count)
{
string procedureName = storedProcedurePrefix + table.Name + "Select";
string fileName;
if (createMultipleFiles)
{
fileName = Path.Combine(path, procedureName + ".sql");
}
else
{
fileName = Path.Combine(path, "StoredProcedures.sql");
}
using (StreamWriter writer = new StreamWriter(fileName, true))
{
if (createMultipleFiles == false)
{
writer.WriteLine();
writer.WriteLine("/******************************************************************************");
writer.WriteLine("******************************************************************************/");
}
writer.WriteLine("if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[" + procedureName + "]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)");
writer.WriteLine("\tdrop procedure [dbo].[" + procedureName + "]");
writer.WriteLine("GO");
writer.WriteLine();
writer.WriteLine("CREATE PROCEDURE [dbo].[" + procedureName + "]");
writer.WriteLine("(");
for (int i = 0; i < table.PrimaryKeys.Count; i++)
{
Column column = table.PrimaryKeys[i];
if (i == (table.PrimaryKeys.Count - 1))
{
writer.WriteLine("\t" + AppUtility.CreateParameterString(column, false));
}
else
{
writer.WriteLine
("\t" + AppUtility.CreateParameterString(column, false) + ",");
}
}
writer.WriteLine(")");
writer.WriteLine();
writer.WriteLine("AS");
writer.WriteLine();
writer.WriteLine("SET NOCOUNT ON");
writer.WriteLine();
writer.Write("SELECT");
for (int i = 0; i < table.Columns.Count; i++)
{
Column column = table.Columns[i];
if (i == 0)
{
writer.Write(" ");
}
else
{
writer.Write("\t");
}
writer.Write("[" + column.Name + "]");
if (i < (table.Columns.Count - 1))
{
writer.Write(",");
}
writer.WriteLine();
}
writer.WriteLine("FROM [" + table.Name + "]");
writer.Write("WHERE");
for (int i = 0; i < table.PrimaryKeys.Count; i++) { Column column =
table.PrimaryKeys[i]; if (i == 0) { writer.WriteLine(" [" +
column.Name + "] = @" + column.Name); } else
{ writer.WriteLine("\tAND [" + column.Name + "] =
@" + column.Name); } }
writer.WriteLine("GO"); {
writer.WriteLine();
writer.WriteLine("GRANT EXECUTE ON [dbo].[" +
procedureName + "] TO [" + grantLoginName + "]");
writer.WriteLine("GO");
}
}
}
}
internal static void CreateSelectAllStoredProcedure(Table table,
string grantLoginName, string storedProcedurePrefix, string path, bool createMultipleFiles)
{
if (table.PrimaryKeys.Count > 0 && table.ForeignKeys.Count != table.Columns.Count)
{
string procedureName = storedProcedurePrefix + table.Name + "SelectAll";
string fileName;
if (createMultipleFiles)
{
fileName = Path.Combine(path, procedureName + ".sql");
}
else
{
fileName = Path.Combine(path, "StoredProcedures.sql");
}
using (StreamWriter writer = new StreamWriter(fileName, true))
{
if (createMultipleFiles == false)
{
writer.WriteLine();
writer.WriteLine("/******************************************************************************");
writer.WriteLine("******************************************************************************/");
}
writer.WriteLine("if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[" + procedureName + "]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)");
writer.WriteLine("\tdrop procedure [dbo].[" + procedureName + "]");
writer.WriteLine("GO");
writer.WriteLine();
writer.WriteLine("CREATE PROCEDURE [dbo].[" + procedureName + "]");
writer.WriteLine();
writer.WriteLine("AS");
writer.WriteLine();
writer.WriteLine("SET NOCOUNT ON");
writer.WriteLine();
writer.Write("SELECT");
for (int i = 0; i < table.Columns.Count; i++)
{
Column column = table.Columns[i];
if (i == 0)
{
writer.Write(" ");
}
else
{
writer.Write("\t");
}
writer.Write("[" + column.Name + "]");
if (i < (table.Columns.Count - 1)) { writer.Write(","); }
writer.WriteLine(); } writer.WriteLine("FROM [" + table.Name + "]");
writer.WriteLine("GO"); {
writer.WriteLine();
writer.WriteLine("GRANT EXECUTE ON [dbo].[" +
procedureName + "] TO [" + grantLoginName + "]");
writer.WriteLine("GO");
}
}
}
}
internal static void CreateSelectAllByStoredProcedures(Table table,
string grantLoginName, string storedProcedurePrefix, string path, bool createMultipleFiles)
{
foreach (List<Column> compositeKeyList in table.ForeignKeys.Values)
{
StringBuilder stringBuilder = new StringBuilder(255);
stringBuilder.Append(storedProcedurePrefix + table.Name + "SelectAllBy");
for (int i = 0; i < compositeKeyList.Count; i++)
{ Column column = compositeKeyList[i]; if (i > 0)
{
stringBuilder.Append("_" + AppUtility.FormatPascal(column.Name));
}
else
{
stringBuilder.Append(AppUtility.FormatPascal(column.Name));
}
}
string procedureName = stringBuilder.ToString();
string fileName;
if (createMultipleFiles)
{
fileName = Path.Combine(path, procedureName + ".sql");
}
else
{
fileName = Path.Combine(path, "StoredProcedures.sql");
}
using (StreamWriter writer = new StreamWriter(fileName, true))
{
if (createMultipleFiles == false)
{
writer.WriteLine();
writer.WriteLine("/******************************************************************************");
writer.WriteLine("******************************************************************************/");
}
writer.WriteLine("if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[" + procedureName + "]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)");
writer.WriteLine("\tdrop procedure [dbo].[" + procedureName + "]");
writer.WriteLine("GO");
writer.WriteLine();
writer.WriteLine("CREATE PROCEDURE [dbo].[" + procedureName + "]");
writer.WriteLine("(");
for (int i = 0; i < compositeKeyList.Count; i++)
{
Column column = compositeKeyList[i];
if (i < (compositeKeyList.Count - 1))
{
writer.WriteLine
("\t" + AppUtility.CreateParameterString(column, false) + ",");
}
else
{
writer.WriteLine("\t" + AppUtility.CreateParameterString(column, false));
}
}
writer.WriteLine(")");
writer.WriteLine();
writer.WriteLine("AS");
writer.WriteLine();
writer.WriteLine("SET NOCOUNT ON");
writer.WriteLine();
writer.Write("SELECT");
for (int i = 0; i < table.Columns.Count; i++)
{
Column column = table.Columns[i];
if (i == 0)
{
writer.Write(" ");
}
else
{
writer.Write("\t");
}
writer.Write("[" + column.Name + "]");
if (i < (table.Columns.Count - 1))
{
writer.Write(",");
}
writer.WriteLine();
}
writer.WriteLine("FROM [" + table.Name + "]");
writer.Write("WHERE");
for (int i = 0; i < compositeKeyList.Count; i++)
{ Column column = compositeKeyList[i]; if (i == 0)
{ writer.WriteLine(" [" + column.Name + "] =
@" + column.Name); } else { writer.WriteLine("\tAND
[" + column.Name + "] = @" + column.Name); } }
writer.WriteLine("GO"); {
writer.WriteLine();
writer.WriteLine("GRANT EXECUTE ON [dbo].[" +
procedureName + "] TO [" + grantLoginName + "]");
writer.WriteLine("GO");
}
}
}
}
Now let's understand the code of ‘Generate Classes’ button click event handler given as below:
private void btnGenClasses_Click(object sender, EventArgs e)
{
try
{
GenerateCSharpClasses();
MessageBox.Show("Class file(s) created
Successfully at path mentioned in 'Class Files Path'", "Success");
grpOutPut.Visible = true;
}
catch (Exception ex)
{
MessageBox.Show("Error : " + ex.Message,
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
The above written code uses the following methods in order to generate C# POCO classes and Dapper Repo classes of selected tables:
private void GenerateCSharpClasses()
{
string sFolderPath, sNameSpace;
if (txtNamespace.Text.Trim() != "")
{
sFolderPath = CreateOutputDir(txtNamespace.Text.Trim());
sNameSpace = txtNamespace.Text.Trim();
}
else
{
sFolderPath = CreateOutputDir(mSSqlDatabase);
sNameSpace = mSSqlDatabase;
}
CreateBaseRepoClass(sFolderPath + "\\BaseRepository.cs", sNameSpace);
var objTableNames = new ArrayList();
string sConString = "";
sConString = txtConnectionString.Text +
";Initial Catalog=" + mSSqlDatabase;
for (int iTableCount = 0; iTableCount
< cblTableList.CheckedItems.Count; iTableCount++)
{
objTableNames.Add(cblTableList.CheckedItems[iTableCount].ToString());
}
txtFilesPath.Text = CSharpCodeGenerator.GenerateClassFiles
(sFolderPath, sConString, txtSPPrefix.Text.Trim(), sNameSpace, "", objTableNames);
CSharpCodeGenerator.GenerateRepoFiles(sFolderPath, sConString,
txtSPPrefix.Text.Trim(), sNameSpace, "", objTableNames);
}
private void CreateBaseRepoClass(string aSFilePath, string targetNamespace)
{
using (var streamWriter = new StreamWriter(aSFilePath))
{
#region Add Referances
streamWriter.WriteLine("using System;");
streamWriter.WriteLine("using System.Data;");
streamWriter.WriteLine("using System.Data.SqlClient;");
streamWriter.WriteLine("using System.Linq;");
streamWriter.WriteLine("using System.Web.Configuration;");
streamWriter.WriteLine();
streamWriter.WriteLine("namespace " + targetNamespace);
streamWriter.WriteLine("{");
#endregion
#region Create Base Repository Class
streamWriter.WriteLine("\t public abstract class BaseRepository ");
streamWriter.WriteLine("\t\t {");
streamWriter.WriteLine(
"\t\t\t protected static void SetIdentity<T>
(IDbConnection connection, Action<T> setId) ");
streamWriter.WriteLine("\t\t\t {");
streamWriter.WriteLine(
"\t\t\t dynamic identity =
connection.Query(\"SELECT @@IDENTITY AS Id\").Single(); ");
streamWriter.WriteLine("\t\t\t T newId = (T)identity.Id; ");
streamWriter.WriteLine("\t\t\t setId(newId); ");
streamWriter.WriteLine("\t\t\t }");
streamWriter.WriteLine(
"\t\t\t protected static IDbConnection OpenConnection() ");
streamWriter.WriteLine("\t\t\t {");
streamWriter.WriteLine(
"\t\t\t IDbConnection connection =
new SqlConnection(WebConfigurationManager.ConnectionStrings
[\"DBConString\"].ConnectionString); ");
streamWriter.WriteLine("\t\t\t connection.Open(); ");
streamWriter.WriteLine("\t\t\t return connection; ");
streamWriter.WriteLine("\t\t\t }");
streamWriter.WriteLine("\t\t }");
#endregion
}
}
‘GenerateCSharpClasses
’ method first creates the folder to save the output files using method, then it creates the BaseRepository
class using ‘CreateBaseRepoClass
’ method (this is used as base class for all the Dapper Repo Classes) and then it loops through each selected table of the list and generate the C# POCO class files using ‘GenerateClassFiles
’ and Dapper Repo files using ‘GenerateRepoFiles
’ method of ‘CSharpCodeGenerator
’ class.
The code of ‘GenerateClassFiles
’ method of ‘CSharpCodeGenerator
’ is as follows:
public static string GenerateClassFiles(string outputDirectory,
string connectionString, string storedProcedurePrefix,
string targetNamespace, string daoSuffix, ArrayList tableNames)
{
string databaseName = "";
string csPath;
csPath = Path.Combine(outputDirectory, "CS");
List<Table> tableList = AppUtility.GetTableList
(connectionString, outputDirectory, tableNames, ref databaseName);
if (tableList.Count <= 0) return csPath;
AppUtility.CreateSubDirectory(csPath, true);
foreach (Table table in tableList)
{
CreateModelClass(databaseName, table,
targetNamespace, storedProcedurePrefix, csPath);
}
return csPath;
}
In the above ‘GenerateClassFiles
’ method, the application first gets the table list of the given database using ‘GetTableList
’ method and then it generates the C# POCO class definition files of all the tables present in tables list by looping through each table and using ‘CreateModelClass
’ method. The code of ‘CreateModelClass
’ method is as follows:
internal static void CreateModelClass(string databaseName,
Table table, string targetNamespace, string storedProcedurePrefix, string path)
{
var className = AppUtility.FormatClassName(table.Name);
using (var streamWriter = new StreamWriter(Path.Combine(path, className + ".cs")))
{
#region Create the header for the class
streamWriter.WriteLine("using System;");
streamWriter.WriteLine();
streamWriter.WriteLine("namespace " + targetNamespace);
streamWriter.WriteLine("{");
streamWriter.WriteLine("\tpublic class " + className);
streamWriter.WriteLine("\t{");
#endregion
#region Append the public properties
streamWriter.WriteLine("\t\t#region Properties");
for (var i = 0; i < table.Columns.Count; i++)
{
var column = table.Columns[i];
var parameter = AppUtility.CreateMethodParameter(column);
var type = parameter.Split(' ')[0];
var name = parameter.Split(' ')[1];
streamWriter.WriteLine("\t\t///<summary>");
streamWriter.WriteLine("\t\t/// Gets or sets the " +
AppUtility.FormatPascal(name) + " value.");
streamWriter.WriteLine("\t\t/// </summary>");
streamWriter.WriteLine("\t\tpublic " +
type + " " + AppUtility.FormatPascal(name));
streamWriter.WriteLine("\t\t{ get; set; }");
if (i < (table.Columns.Count - 1))
{
streamWriter.WriteLine();
}
}
streamWriter.WriteLine();
streamWriter.WriteLine("\t\t#endregion");
#endregion
streamWriter.WriteLine("\t}");
streamWriter.WriteLine("}");
}
}
The code of ‘GenerateRepoFiles
’ method of ‘CSharpCodeGenerator
’ is as follows:
public static string GenerateRepoFiles(string outputDirectory,
string connectionString, string storedProcedurePrefix,
string targetNamespace, string daoSuffix, ArrayList tableNames)
{
string databaseName = "";
string csPath = Path.Combine(outputDirectory, "Repo");
List<Table> tableList = AppUtility.GetTableList
(connectionString, outputDirectory, tableNames, ref databaseName);
if (tableList.Count <= 0) return csPath;
AppUtility.CreateSubDirectory(csPath, true);
foreach (Table table in tableList)
{
CreateRepoClass(databaseName, table, targetNamespace, storedProcedurePrefix, csPath);
}
return csPath;
}
In the above ‘GenerateRepoFiles
’ method, the application first gets the tables list of the given database using ‘AppUtility.GetTableList
’ method and then it loops through each table present in tables list to generate Dapper Repo files containing CRUD operation methods using ‘CreateRepoClass
’ method. The code of ‘CreateRepoClass
’ method is as follows:
internal static void CreateRepoClass(string databaseName,
Table table, string targetNamespace, string storedProcedurePrefix, string path)
{
var className = AppUtility.FormatClassName(table.Name);
using (var streamWriter =
new StreamWriter(Path.Combine(path, className + ".cs")))
{
#region Add References & Declare Class
streamWriter.WriteLine("using System.Collections.Generic;");
streamWriter.WriteLine("using System.Data;");
streamWriter.WriteLine("using System.Linq;");
streamWriter.WriteLine("using Dapper;");
streamWriter.WriteLine();
streamWriter.WriteLine("namespace " + targetNamespace);
streamWriter.WriteLine("{");
streamWriter.WriteLine("\t public class " +
className + "Repo : BaseRepository");
streamWriter.WriteLine("\t\t {");
#endregion
#region Append the access methods
streamWriter.WriteLine("\t\t#region Methods");
streamWriter.WriteLine();
CreateInsertMethod(table, streamWriter);
CreateUpdateMethod(table, streamWriter);
CreateSelectMethod(table, streamWriter);
CreateSelectAllMethod(table, streamWriter);
CreateSelectAllByMethods(table, storedProcedurePrefix, streamWriter);
#endregion
streamWriter.WriteLine();
streamWriter.WriteLine("\t\t#endregion");
streamWriter.WriteLine("\t\t}");
streamWriter.WriteLine("}");
}
}
In the above ‘CreateRepoClass
’, the application generates a class which is named as ‘Repo
’ containing methods for Insert
, Update
, Select
& Select All
operations for the given table. The code of methods used in ‘CreateRepoClass
’ method are as follows:
private static void CreateInsertMethod(Table table, TextWriter streamWriter)
{
var className = AppUtility.FormatClassName(table.Name);
var variableName = "a" + className;
streamWriter.WriteLine("\t\t/// <summary>");
streamWriter.WriteLine
("\t\t/// Saves a record to the " + table.Name + " table.");
streamWriter.WriteLine
("\t\t/// returns True if value saved successfully else false");
streamWriter.WriteLine
("\t\t/// Throw exception with message value 'EXISTS' if the data is duplicate");
streamWriter.WriteLine
("\t\t/// </summary>");
streamWriter.WriteLine
("\t\tpublic bool Insert
(" + className + " " + variableName + ")");
streamWriter.WriteLine("\t\t{");
streamWriter.WriteLine
("\t\t var blResult = false;");
streamWriter.WriteLine
("\t\t\t using (var vConn = OpenConnection())");
streamWriter.WriteLine("\t\t\t\t {");
streamWriter.WriteLine
("\t\t\t\t var vParams = new DynamicParameters();");
foreach (var column in table.Columns)
{ streamWriter.WriteLine("\t\t\t\t\t vParams.Add
(\"@" + column.Name + "\"," +
variableName + "." + AppUtility.FormatPascal(column.Name) + ");"); }
streamWriter.WriteLine("\t\t\t\t\t int iResult =
vConn.Execute(\"" + table.Name + "Insert\",
vParams, commandType: CommandType.StoredProcedure);");
streamWriter.WriteLine("\t\t\t if (iResult == -1) blResult = true;");
streamWriter.WriteLine("\t\t\t }");
streamWriter.WriteLine("\t\t\t return blResult;");
streamWriter.WriteLine("\t\t}");
streamWriter.WriteLine();
}
private static void CreateUpdateMethod(Table table, TextWriter streamWriter)
{
if (table.PrimaryKeys.Count <= 0 || table.Columns.Count == table.PrimaryKeys.Count ||
table.Columns.Count == table.ForeignKeys.Count) return;
var className = AppUtility.FormatClassName(table.Name);
var variableName = "a" + className;
streamWriter.WriteLine("\t\t/// <summary>");
streamWriter.WriteLine
("\t\t/// Updates record to the " + table.Name + " table.");
streamWriter.WriteLine
("\t\t/// returns True if value saved successfully else false");
streamWriter.WriteLine
("\t\t/// Throw exception with message value 'EXISTS' if the data is duplicate");
streamWriter.WriteLine
("\t\t/// </summary>");
streamWriter.WriteLine
("\t\tpublic bool Update(" + className + " " + variableName + ")");
streamWriter.WriteLine("\t\t{");
streamWriter.WriteLine
("\t\t var blResult = false;");
streamWriter.WriteLine
("\t\t\t using (var vConn = OpenConnection())");
streamWriter.WriteLine("\t\t\t\t {");
streamWriter.WriteLine
("\t\t\t\t var vParams = new DynamicParameters();");
foreach (var column in table.Columns)
{ streamWriter.WriteLine
("\t\t\t\t\t vParams.Add(\"@" + column.Name +
"\"," + variableName + "." +
AppUtility.FormatPascal(column.Name) + ");"); }
streamWriter.WriteLine("\t\t\t\t\t int iResult = vConn.Execute
(\"" + table.Name + "Update\", vParams,
commandType: CommandType.StoredProcedure);");
streamWriter.WriteLine("\t\t\t\t if (iResult == -1) blResult = true;");
streamWriter.WriteLine("\t\t\t\t }");
streamWriter.WriteLine("\t\t\treturn blResult;");
streamWriter.WriteLine("\t\t}");
streamWriter.WriteLine();
}
private static void CreateSelectMethod(Table table, TextWriter streamWriter)
{
if (table.PrimaryKeys.Count <= 0 || table.Columns.Count == table.PrimaryKeys.Count ||
table.Columns.Count == table.ForeignKeys.Count) return;
var className = AppUtility.FormatClassName(table.Name);
var variableName = "a" + table.PrimaryKeys[0].Name;
streamWriter.WriteLine("\t\t/// <summary>");
streamWriter.WriteLine
("\t\t/// Selects the Single object of " + table.Name + " table.");
streamWriter.WriteLine("\t\t/// </summary>");
streamWriter.WriteLine
("\t\tpublic "+ className + " Get"+ className +
"(" + AppUtility.GetCsType(table.PrimaryKeys[0]) + " " + variableName + ")");
streamWriter.WriteLine("\t\t{");
streamWriter.WriteLine("\t\t\t using (var vConn = OpenConnection())");
streamWriter.WriteLine("\t\t\t\t {");
streamWriter.WriteLine("\t\t\t\t var vParams = new DynamicParameters();");
streamWriter.WriteLine("\t\t\t\t\t vParams.Add
(\"@" + table.PrimaryKeys[0].Name + "\"," + variableName + ");");
streamWriter.WriteLine("\t\t\t\t\t return vConn.Query<"+
className + ">(\"" + table.Name + "Select\",
vParams, commandType: CommandType.StoredProcedure);");
streamWriter.WriteLine("\t\t\t\t }");
streamWriter.WriteLine("\t\t}");
streamWriter.WriteLine();
}
private static void CreateSelectAllMethod(Table table, TextWriter streamWriter)
{
if (table.Columns.Count == table.PrimaryKeys.Count ||
table.Columns.Count == table.ForeignKeys.Count)
return;
var className = AppUtility.FormatClassName(table.Name);
streamWriter.WriteLine
("\t\t/// <summary>");
streamWriter.WriteLine
("\t\t/// Selects all records from the " + table.Name + " table.");
streamWriter.WriteLine("\t\t/// </summary>");
streamWriter.WriteLine
("\t\t public IEnumerable<" + className + "> SelectAll()");
streamWriter.WriteLine("\t\t{");
streamWriter.WriteLine("\t\t\t using (var vConn = OpenConnection())");
streamWriter.WriteLine("\t\t\t{");
streamWriter.WriteLine("\t\t\t\t return vConn.Query<" +
className + ">(\"" + table.Name +
"SelectAll\", commandType: CommandType.StoredProcedure).ToList();");
streamWriter.WriteLine("\t\t\t}");
streamWriter.WriteLine("\t\t}");
}
private static void CreateSelectAllByMethods
(Table table, string storedProcedurePrefix, TextWriter streamWriter)
{
string className = AppUtility.FormatClassName(table.Name);
string dtoVariableName = AppUtility.FormatCamel(className);
foreach (List<Column> compositeKeyList in table.ForeignKeys.Values)
{
StringBuilder stringBuilder = new StringBuilder(255);
stringBuilder.Append("SelectAllBy");
for (var i = 0; i < compositeKeyList.Count; i++)
{
var column = compositeKeyList[i];
if (i > 0)
{
stringBuilder.Append("_" + AppUtility.FormatPascal(column.Name));
}
else
{
stringBuilder.Append(AppUtility.FormatPascal(column.Name));
}
}
string methodName = stringBuilder.ToString();
string procedureName = storedProcedurePrefix + table.Name + methodName;
streamWriter.WriteLine("\t\t/// <summary>");
streamWriter.WriteLine
("\t\t/// Selects all records from the " +
table.Name + " table by a foreign key.");
streamWriter.WriteLine("\t\t/// </summary>");
streamWriter.Write
("\t\tpublic List<" + className + "> " + methodName + "(");
for (int i = 0; i < compositeKeyList.Count; i++)
{
Column column = compositeKeyList[i];
streamWriter.Write(AppUtility.CreateMethodParameter(column));
if (i < (compositeKeyList.Count - 1))
{
streamWriter.Write(",");
}
}
streamWriter.WriteLine(")");
streamWriter.WriteLine("\t\t{");
streamWriter.WriteLine("\t\t\t using (var vConn = OpenConnection())");
streamWriter.WriteLine("\t\t\t\t {");
streamWriter.WriteLine("\t\t\t\t var vParams = new DynamicParameters();");
for (var i = 0; i < compositeKeyList.Count; i++)
{
var column = compositeKeyList[i];
streamWriter.WriteLine
("\t\t\t\t\t vParams.Add(\"@" +
column.Name + "\"," + AppUtility.FormatCamel(column.Name) + ");");
}
streamWriter.WriteLine
("\t\t\t\t return vConn.Query<" + className +
">(\"" + table.Name + "SelectAll\",
vParams, commandType: CommandType.StoredProcedure).ToList();");
streamWriter.WriteLine("\t\t\t\t }");
streamWriter.WriteLine("\t\t}");
streamWriter.WriteLine();
}
}
The ‘Generate Both SQL & Classes’ button click will execute both ‘GenerateSQLScripts
’ & ‘GenerateCSharpClasses
’ methods together and show the output files path after success message like in the given screenshot.
The source code of this application can be downloaded from Github. I always use this application in order to generate POCO classes, DML SQL Scripts and Dapper Repo classes. I hope that it be as useful for other people as it is to me . Let me know if I have missed anything or if you have any queries/suggestions. Happy coding.