Skip to content

Instantly share code, notes, and snippets.

@jburditt
Created November 29, 2017 00:14
Show Gist options
  • Save jburditt/bbb5f1c915dfd55dd80117ee7332a616 to your computer and use it in GitHub Desktop.
Save jburditt/bbb5f1c915dfd55dd80117ee7332a616 to your computer and use it in GitHub Desktop.
Converted T4 to C#
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Database.Copy
{
// copied from OrmLite.core.include T4
public static class DatabaseHelper
{
static Regex rxCleanUp = new Regex(@"[^\w\d_]", RegexOptions.Compiled);
static string[] cs_keywords = { "abstract", "event", "new", "struct", "as", "explicit", "null",
"switch", "base", "extern", "object", "this", "bool", "false", "operator", "throw",
"break", "finally", "out", "true", "byte", "fixed", "override", "try", "case", "float",
"params", "typeof", "catch", "for", "private", "uint", "char", "foreach", "protected",
"ulong", "checked", "goto", "public", "unchecked", "class", "if", "readonly", "unsafe",
"const", "implicit", "ref", "ushort", "continue", "in", "return", "using", "decimal",
"int", "sbyte", "virtual", "default", "interface", "sealed", "volatile", "delegate",
"internal", "short", "void", "do", "is", "sizeof", "while", "double", "lock",
"stackalloc", "else", "long", "static", "enum", "namespace", "string" };
static Func<string, string> CleanUp = (str) =>
{
str = rxCleanUp.Replace(str, "_");
if (char.IsDigit(str[0]))
{
str = "_" + str;
}
else if (cs_keywords.Contains(str))
{
str = "@" + str;
}
return str;
};
public static Tables LoadTables(bool makeSingular)
{
Console.WriteLine("// Connection String Name: `{0}`", ConnectionStringName);
Console.WriteLine("// Provider: `{0}`", ProviderName);
Console.WriteLine("// Connection String: `{0}`", zap_password(ConnectionString));
Console.WriteLine("");
DbProviderFactory _factory;
try
{
_factory = DbProviderFactories.GetFactory(ProviderName);
}
catch (Exception x)
{
var error = x.Message.Replace("\r\n", "\n").Replace("\n", " ");
Console.WriteLine(string.Format("Failed to load provider `{0}` - {1}", ProviderName, error));
Console.WriteLine("");
Console.WriteLine("// -----------------------------------------------------------------------------------------");
Console.WriteLine("// Failed to load provider `{0}` - {1}", ProviderName, error);
Console.WriteLine("// -----------------------------------------------------------------------------------------");
Console.WriteLine("");
return null;
}
Console.WriteLine("// Factory Name: `{0}`", _factory.GetType().Name);
try
{
Tables result;
using (var conn = _factory.CreateConnection())
{
conn.ConnectionString = ConnectionString;
conn.Open();
SchemaReader reader = null;
if (_factory.GetType().Name == "MySqlClientFactory")
{
// MySql
reader = new MySqlSchemaReader();
}
else if (_factory.GetType().Name == "SqlCeProviderFactory")
{
// SQL CE
reader = new SqlServerCeSchemaReader();
}
else if (_factory.GetType().Name == "NpgsqlFactory")
{
// PostgreSQL
reader = new PostGreSqlSchemaReader();
}
else if (_factory.GetType().Name == "OracleClientFactory")
{
// Oracle
reader = new OracleSchemaReader();
}
else if (_factory.GetType().Name == "SQLiteFactory")
{
// Sqlite
reader = new SqliteSchemaReader();
}
else
{
// Assume SQL Server
reader = new SqlServerSchemaReader(IncludeSPReturnTypes);
}
//reader.outer = this;
result = reader.ReadSchema(conn, _factory);
// Remove unrequired tables/views
for (int i = result.Count - 1; i >= 0; i--)
{
if (SchemaName != null && string.Compare(result[i].Schema, SchemaName, true) != 0)
{
result.RemoveAt(i);
continue;
}
if ((!IncludeViews && result[i].IsView) || (!IncludeFunctions && result[i].IsFunction))
{
result.RemoveAt(i);
continue;
}
}
}
var rxClean = new Regex("^(Equals|GetHashCode|GetType|ToString|repo|Save|IsNew|Insert|Update|Delete|Exists|SingleOrDefault|Single|First|FirstOrDefault|Fetch|Page|Query)$");
foreach (var t in result)
{
if (!makeSingular)
{
t.ClassName = t.CleanName;
}
t.ClassName = ClassPrefix + t.ClassName + ClassSuffix;
foreach (var c in t.Columns)
{
c.PropertyName = rxClean.Replace(c.PropertyName, "_$1");
// Make sure property name doesn't clash with class name
if (c.PropertyName == t.ClassName)
c.PropertyName = "_" + c.PropertyName;
}
}
return result;
}
catch (Exception x)
{
var error = x.Message.Replace("\r\n", "\n").Replace("\n", " ");
Console.WriteLine(string.Format("Failed to read database schema - {0}", error));
Console.WriteLine("");
Console.WriteLine("// -----------------------------------------------------------------------------------------");
Console.WriteLine("// Failed to read database schema - {0}", error);
Console.WriteLine("// -----------------------------------------------------------------------------------------");
Console.WriteLine("");
return null;
}
}
static string ConnectionStringName = "";
public static string ProviderName = "";
public static string ConnectionString = "";
static string Namespace = "";
static string ClassPrefix = "";
static string ClassSuffix = "";
static string SchemaName = null;
static bool IncludeViews = false;
static bool IncludeFunctions = false;
static bool IncludeSPReturnTypes = false; //Will create {StoredProcName}_Result classes for any SPs with output results
public class Table
{
public List<Column> Columns;
public List<TableIndex> Indices;
public List<FKey> FKeys;
public string Name;
public string Schema;
public bool IsView;
public bool IsFunction;
public string CleanName;
public string ClassName;
public string SequenceName;
public bool Ignore;
public string SQL;
public Column PK
{
get
{
return this.Columns.SingleOrDefault(x => x.IsPK);
}
}
public Column GetColumn(string columnName)
{
return Columns.Single(x => string.Compare(x.Name, columnName, true) == 0);
}
public Column this[string columnName]
{
get
{
return GetColumn(columnName);
}
}
public bool HasPK()
{
return ((PK != null) && (string.IsNullOrEmpty(PK.Name) != true));
}
public TableIndex GetIndex(string indexName)
{
return Indices.Single(x => string.Compare(x.Name, indexName, true) == 0);
}
}
public class Column
{
public string Name;
public string PropertyName;
public string PropertyType;
public bool IsPK;
public bool IsNullable;
public bool IsAutoIncrement;
public bool IsComputed;
public bool Ignore;
public int Size;
public int Precision;
public string DefaultValue;
public string ProperPropertyType
{
get
{
if (IsNullable)
{
return PropertyType + CheckNullable(this);
}
return PropertyType;
}
}
}
public class Tables : List<Table>
{
public Tables()
{
}
public Table GetTable(string tableName)
{
return this.Single(x => string.Compare(x.Name, tableName, true) == 0);
}
public Table this[string tableName]
{
get
{
return GetTable(tableName);
}
}
}
public class IndexColumn
{
public string Name;
public bool IsAsc;
}
public class TableIndex
{
public string Name;
public List<IndexColumn> IndexColumns;
public bool IsUnique;
public string SQL;
}
public class FKey
{
public string ToTable;
public string ToTableSingular;
public string FromColumn;
public string ToColumn;
}
public class SP
{
public string Name;
public string CleanName;
public string ClassName;
public string Schema;
public string SchemaQualifiedName { get { return Schema + "." + Name; } }
public List<SPParam> Parameters;
public List<SPOutputColumn> SPOutputColumns;
public SP()
{
Parameters = new List<SPParam>();
SPOutputColumns = new List<SPOutputColumn>();
}
public string ArgList
{
get
{
StringBuilder sb = new StringBuilder();
int loopCount = 1;
foreach (var par in Parameters)
{
sb.AppendFormat("{0} {1}", par.SysType, par.CleanName);
if (loopCount < Parameters.Count)
sb.Append(",");
loopCount++;
}
return sb.ToString();
}
}
}
public class SPOutputColumn
{
public string Name;
public string DotNetType;
}
public enum SPParamDir
{
OutDirection,
InDirection,
InAndOutDirection
}
public class SPParam
{
public string Name;
public string CleanName;
public string SysType;
public string NullableSysType;
public string DbType;
public SPParamDir Direction;
}
static string CheckNullable(Column col)
{
string result = "";
if (col.IsNullable &&
col.PropertyType != "byte[]" &&
col.PropertyType != "string" &&
col.PropertyType != "Microsoft.SqlServer.Types.SqlGeography" &&
col.PropertyType != "Microsoft.SqlServer.Types.SqlGeometry"
)
result = "?";
return result;
}
static string zap_password(string connectionString)
{
var rx = new Regex("password=.*;", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.IgnoreCase);
return rx.Replace(connectionString, "password=**zapped**;");
}
static string GetColumnDefaultValue(Column col)
{
string sysType = string.Format("\"{0}\"", col.DefaultValue);
switch (col.PropertyType.ToLower())
{
case "long":
case "int":
case "double":
case "decimal":
case "bool":
sysType = col.DefaultValue.ToString().Replace("'", "").Replace("\"", "");
break;
case "guid":
sysType = string.Format("\"{0}\"", col.DefaultValue);
break;
case "datetime":
{
if (col.DefaultValue.ToLower() == "current_time" || col.DefaultValue.ToLower() == "current_date" || col.DefaultValue.ToLower() == "current_timestamp")
sysType = "SystemMethods.CurrentDateTime";
else
sysType = "\"" + col.DefaultValue + "\"";
break;
}
}
return sysType;
}
static List<SP> SPsNotSupported(string providerName)
{
Console.WriteLine("SP function creation is not supported for " + providerName);
Console.WriteLine("");
Console.WriteLine("// -----------------------------------------------------------------------------------------");
Console.WriteLine("// SP function creation is not supported for `{0}`", providerName);
Console.WriteLine("// -----------------------------------------------------------------------------------------");
return new List<SP>();
}
static string GetParamDirection(SPParamDir direction)
{
switch (direction)
{
case SPParamDir.InAndOutDirection:
return "ParameterDirection.InputOutput";
case SPParamDir.OutDirection:
return "ParameterDirection.Output";
case SPParamDir.InDirection:
default:
return "ParameterDirection.Input";
}
}
static List<SP> LoadSPs()
{
Console.WriteLine("// This file was automatically generated by the PetaPoco T4 Template");
Console.WriteLine("// Do not make changes directly to this file - edit the template instead");
Console.WriteLine("// ");
Console.WriteLine("// The following connection settings were used to generate this file");
Console.WriteLine("// ");
Console.WriteLine("// Connection String Name: `{0}`", ConnectionStringName);
Console.WriteLine("// Provider: `{0}`", ProviderName);
Console.WriteLine("// Connection String: `{0}`", zap_password(ConnectionString));
Console.WriteLine("");
DbProviderFactory _factory;
try
{
_factory = DbProviderFactories.GetFactory(ProviderName);
}
catch (Exception x)
{
var error = x.Message.Replace("\r\n", "\n").Replace("\n", " ");
Console.WriteLine(string.Format("Failed to load provider `{0}` - {1}", ProviderName, error));
Console.WriteLine("");
Console.WriteLine("// -----------------------------------------------------------------------------------------");
Console.WriteLine("// Failed to load provider `{0}` - {1}", ProviderName, error);
Console.WriteLine("// -----------------------------------------------------------------------------------------");
Console.WriteLine("");
return null;
}
Console.WriteLine("// Factory Name: `{0}`", _factory.GetType().Name);
try
{
List<SP> result;
using (var conn = _factory.CreateConnection())
{
conn.ConnectionString = ConnectionString;
conn.Open();
SchemaReader reader = null;
if (_factory.GetType().Name == "MySqlClientFactory")
{
// MySql
reader = new MySqlSchemaReader();
return SPsNotSupported(ProviderName);
}
else if (_factory.GetType().Name == "SqlCeProviderFactory")
{
// SQL CE
reader = new SqlServerCeSchemaReader();
return SPsNotSupported(ProviderName);
}
else if (_factory.GetType().Name == "NpgsqlFactory")
{
// PostgreSQL
reader = new PostGreSqlSchemaReader();
return SPsNotSupported(ProviderName);
}
else if (_factory.GetType().Name == "OracleClientFactory")
{
// Oracle
reader = new OracleSchemaReader();
return SPsNotSupported(ProviderName);
}
else if (_factory.GetType().Name == "SQLiteFactory")
{
// Sqlite
reader = new SqliteSchemaReader();
return SPsNotSupported(ProviderName);
}
else
{
// Assume SQL Server
reader = new SqlServerSchemaReader(IncludeSPReturnTypes);
}
result = reader.ReadSPList(conn, _factory);
// Remove unrequired procedures
for (int i = result.Count - 1; i >= 0; i--)
{
if (SchemaName != null && string.Compare(result[i].Schema, SchemaName, true) != 0)
{
result.RemoveAt(i);
continue;
}
}
}
return result;
}
catch (Exception x)
{
var error = x.Message.Replace("\r\n", "\n").Replace("\n", " ");
Console.WriteLine(string.Format("Failed to read database schema - {0}", error));
Console.WriteLine("");
Console.WriteLine("// -----------------------------------------------------------------------------------------");
Console.WriteLine("// Failed to read database schema - {0}", error);
Console.WriteLine("// -----------------------------------------------------------------------------------------");
Console.WriteLine("");
return null;
}
}
static bool IsTableNameInList(string tableName, Tables tbls)
{
if (tbls == null)
return false;
foreach (var tbItem in tbls)
{
if (String.Equals(tbItem.Name, tableName, StringComparison.InvariantCultureIgnoreCase))
{
return true;
}
}
return false;
}
static Table GetTableFromListByName(string tableName, Tables tbls)
{
if (tbls == null)
return null;
foreach (var tbItem in tbls)
{
if (String.Equals(tbItem.Name, tableName, StringComparison.InvariantCultureIgnoreCase))
{
return tbItem;
}
}
return null;
}
abstract class SchemaReader
{
public abstract Tables ReadSchema(DbConnection connection, DbProviderFactory factory);
public abstract List<SP> ReadSPList(DbConnection connection, DbProviderFactory factory);
public void WriteLine(string o)
{
Console.WriteLine(o);
}
}
static int GetDatatypePrecision(string type)
{
int startPos = type.IndexOf(",");
if (startPos < 0)
return -1;
int endPos = type.IndexOf(")");
if (endPos < 0)
return -1;
string typePrecisionStr = type.Substring(startPos + 1, endPos - startPos - 1);
int result = -1;
if (int.TryParse(typePrecisionStr, out result))
return result;
else
return -1;
}
static int GetDatatypeSize(string type)
{
int startPos = type.IndexOf("(");
if (startPos < 0)
return -1;
int endPos = type.IndexOf(",");
if (endPos < 0)
{
endPos = type.IndexOf(")");
}
string typeSizeStr = type.Substring(startPos + 1, endPos - startPos - 1);
int result = -1;
if (int.TryParse(typeSizeStr, out result))
return result;
else
return -1;
}
// Edit here to get a method to read the proc
class SqlServerSchemaReader : SchemaReader
{
private bool IncludeSPReturnTypes;
public SqlServerSchemaReader(bool includeSPReturnTypes)
{
IncludeSPReturnTypes = includeSPReturnTypes;
}
// SchemaReader.ReadSchema
public override Tables ReadSchema(DbConnection connection, DbProviderFactory factory)
{
var result = new Tables();
_connection = connection;
_factory = factory;
var cmd = _factory.CreateCommand();
cmd.Connection = connection;
cmd.CommandText = TABLE_SQL;
//pull the tables in a reader
using (cmd)
{
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Table tbl = new Table();
tbl.Name = rdr["TABLE_NAME"].ToString();
tbl.Schema = rdr["TABLE_SCHEMA"].ToString();
tbl.IsView = string.Compare(rdr["TABLE_TYPE"].ToString(), "View", true) == 0;
tbl.IsFunction = string.Compare(rdr["TABLE_TYPE"].ToString(), "TVF", true) == 0;
tbl.CleanName = CleanUp(tbl.Name);
tbl.ClassName = Inflector.MakeSingular(tbl.CleanName);
result.Add(tbl);
}
}
}
var cmdFks = _factory.CreateCommand();
cmdFks.Connection = connection;
cmdFks.CommandText = FOREIGN_KEYS_SQL;
//get all the foreign keys and add them to the tables.
using (cmdFks)
{
using (var rdr = cmdFks.ExecuteReader())
{
while (rdr.Read())
{
var tableName = rdr["TableWithForeignKey"].ToString();
var table = result.FirstOrDefault(x => x.Name == tableName);
if (table != null)
{
if (table.FKeys == null)
{
table.FKeys = new List<FKey>();
}
var newForeignKey = new FKey();
newForeignKey.ToTable = rdr["TargetTable"].ToString();
newForeignKey.ToTableSingular = Inflector.MakeSingular(CleanUp(newForeignKey.ToTable));
newForeignKey.FromColumn = rdr["ForeignKeyColumn"].ToString();
newForeignKey.ToColumn = rdr["TargetTableKey"].ToString();
table.FKeys.Add(newForeignKey);
}
}
}
}
foreach (var tbl in result)
{
tbl.Columns = LoadColumns(tbl);
// Mark the primary key
string PrimaryKey = GetPK(tbl.Name);
var pkColumn = tbl.Columns.SingleOrDefault(x => x.Name.ToLower().Trim() == PrimaryKey.ToLower().Trim());
if (pkColumn != null)
{
pkColumn.IsPK = true;
}
}
return result;
}
public override List<SP> ReadSPList(DbConnection connection, DbProviderFactory factory)
{
var result = new List<SP>();
_connection = connection;
_factory = factory;
var cmd = _factory.CreateCommand();
cmd.Connection = connection;
cmd.CommandText = SP_NAMES_SQL;
//pull the tables in a reader
using (cmd)
{
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
SP sp = new SP();
sp.Name = rdr["sp_name"].ToString();
sp.Schema = rdr["schema_name"].ToString();
sp.CleanName = CleanUp(sp.Name);
sp.ClassName = Inflector.MakeSingular(sp.CleanName);
result.Add(sp);
}
}
}
foreach (var sp in result)
{
sp.Parameters = LoadSPParams(sp);
if (IncludeSPReturnTypes) sp.SPOutputColumns = LoadSPOutputColumns(sp);
}
return result;
}
DbConnection _connection;
DbProviderFactory _factory;
List<Column> LoadColumns(Table tbl)
{
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = COLUMN_SQL;
var p = cmd.CreateParameter();
p.ParameterName = "@tableName";
p.Value = tbl.Name;
cmd.Parameters.Add(p);
p = cmd.CreateParameter();
p.ParameterName = "@schemaName";
p.Value = tbl.Schema;
cmd.Parameters.Add(p);
var result = new List<Column>();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Column col = new Column();
col.Name = rdr["ColumnName"].ToString();
col.PropertyName = CleanUp(col.Name);
col.PropertyType = GetPropertyType(rdr["DataType"].ToString());
col.Size = GetDatatypeSize(rdr["DataType"].ToString());
col.Precision = GetDatatypePrecision(rdr["DataType"].ToString());
col.IsNullable = rdr["IsNullable"].ToString() == "YES";
col.IsAutoIncrement = ((int)rdr["IsIdentity"]) == 1;
col.IsComputed = ((int)rdr["IsComputed"]) == 1;
result.Add(col);
}
}
return result;
}
}
List<SPParam> LoadSPParams(SP sp)
{
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = SP_PARAMETERS_SQL;
var p = cmd.CreateParameter();
p.ParameterName = "@spname";
p.Value = sp.Name;
cmd.Parameters.Add(p);
var result = new List<SPParam>();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
if (rdr["IS_RESULT"].ToString().ToUpper() == "YES")
continue;
SPParam param = new SPParam();
param.SysType = GetPropertyType(rdr["DATA_TYPE"].ToString());
param.NullableSysType = GetNullablePropertyType(rdr["DATA_TYPE"].ToString());
param.DbType = GetDbType(rdr["DATA_TYPE"].ToString()).ToString();
param.Name = rdr["PARAMETER_NAME"].ToString().Replace("@", "");
param.CleanName = CleanUp(param.Name);
if (rdr["PARAMETER_MODE"].ToString().ToUpper() == "OUT")
param.Direction = SPParamDir.OutDirection;
else if (rdr["PARAMETER_MODE"].ToString().ToUpper() == "IN")
param.Direction = SPParamDir.InDirection;
else
param.Direction = SPParamDir.InAndOutDirection;
result.Add(param);
}
}
return result;
}
}
List<SPOutputColumn> LoadSPOutputColumns(SP sp)
{
var result = new List<SPOutputColumn>();
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = string.Format(@"SELECT name,CAST(is_nullable as VARCHAR(1)) is_nullable,system_type_name FROM sys.dm_exec_describe_first_result_set_for_object(OBJECT_ID('{0}'), 1) WHERE is_hidden = 0", sp.SchemaQualifiedName);
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
if (!rdr.IsDBNull(0))
{
SPOutputColumn param = new SPOutputColumn();
param.Name = rdr["name"].ToString();
var sqlType = rdr["system_type_name"].ToString();
var index = sqlType.IndexOf('('); //Trim off size data
if (index > 0) sqlType = sqlType.Substring(0, index);
var nullable = rdr["is_nullable"].ToString();
if (nullable == "0")
{
param.DotNetType = GetPropertyType(sqlType);
}
else
{
param.DotNetType = GetNullablePropertyType(sqlType);
}
if (!result.Any(t => t.Name == param.Name)) result.Add(param);
}
}
}
}
return result;
}
string GetPK(string table)
{
string sql = @"SELECT c.name AS ColumnName
FROM sys.indexes AS i
INNER JOIN sys.index_columns AS ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
INNER JOIN sys.objects AS o ON i.object_id = o.object_id
LEFT OUTER JOIN sys.columns AS c ON ic.object_id = c.object_id AND c.column_id = ic.column_id
WHERE (i.is_primary_key = 1) AND (o.name = @tableName)";
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = sql;
var p = cmd.CreateParameter();
p.ParameterName = "@tableName";
p.Value = table;
cmd.Parameters.Add(p);
var result = "";
DbDataReader reader = cmd.ExecuteReader();
try
{
if (reader.Read())
{
result = reader[0].ToString();
if (reader.Read())
{
result = "";
}
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
return result;
}
}
string GetPropertyType(string sqlType)
{
string propertyType, dbType;
GetPropertyAndDbType(sqlType, out propertyType, out dbType);
return propertyType;
}
string GetNullablePropertyType(string sqlType)
{
string value = GetPropertyType(sqlType);
if (value.ToUpper() != "STRING" && value.ToUpper() != "BYTE[]")
return value + "?";
else
return value;
}
string GetDbType(string sqlType)
{
string propertyType, dbType;
GetPropertyAndDbType(sqlType, out propertyType, out dbType);
return dbType;
}
void GetPropertyAndDbType(string sqlType, out string propertyType, out string dbType)
{
string sysType = "string";
string sysDbType = "DbType.String";
switch (sqlType)
{
case "varchar":
sysType = "string";
sysDbType = "DbType.AnsiString";
break;
case "bigint":
sysType = "long";
sysDbType = "DbType.Int64";
break;
case "smallint":
sysType = "short";
sysDbType = "DbType.Int16";
break;
case "int":
sysType = "int";
sysDbType = "DbType.Int32";
break;
case "uniqueidentifier":
sysType = "Guid";
sysDbType = "DbType.Guid";
break;
case "smalldatetime":
case "datetime":
case "datetime2":
case "date":
case "time":
sysType = "DateTime";
sysDbType = "DbType.DateTime";
break;
case "datetimeoffset":
sysType = "DateTimeOffset";
sysDbType = "DbType.DateTimeOffset";
break;
case "float":
sysType = "double";
sysDbType = "DbType.Double";
break;
case "real":
sysType = "float";
sysDbType = "DbType.Double";
break;
case "numeric":
case "smallmoney":
case "decimal":
case "money":
sysType = "decimal";
sysDbType = "DbType.Decimal";
break;
case "tinyint":
sysType = "byte";
sysDbType = "DbType.Byte";
break;
case "bit":
sysType = "bool";
sysDbType = "DbType.Boolean";
break;
case "image":
case "binary":
case "varbinary":
case "timestamp":
sysType = "byte[]";
sysDbType = "DbType.Binary";
break;
case "geography":
sysType = "Microsoft.SqlServer.Types.SqlGeography";
sysDbType = "DbType.";
break;
case "geometry":
sysType = "Microsoft.SqlServer.Types.SqlGeometry";
sysDbType = "DbType.";
break;
}
propertyType = sysType;
dbType = sysDbType;
}
string GetDBType(string sqlType)
{
string sysType = "string";
switch (sqlType)
{
case "bigint":
sysType = "long";
break;
case "smallint":
sysType = "short";
break;
case "int":
sysType = "int";
break;
case "uniqueidentifier":
sysType = "Guid";
break;
case "smalldatetime":
case "datetime":
case "datetime2":
case "date":
case "time":
sysType = "DateTime";
break;
case "datetimeoffset":
sysType = "DateTimeOffset";
break;
case "float":
sysType = "double";
break;
case "real":
sysType = "float";
break;
case "numeric":
case "smallmoney":
case "decimal":
case "money":
sysType = "decimal";
break;
case "tinyint":
sysType = "byte";
break;
case "bit":
sysType = "bool";
break;
case "image":
case "binary":
case "varbinary":
case "timestamp":
sysType = "byte[]";
break;
case "geography":
sysType = "Microsoft.SqlServer.Types.SqlGeography";
break;
case "geometry":
sysType = "Microsoft.SqlServer.Types.SqlGeometry";
break;
}
return sysType;
}
const string TABLE_SQL = @"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' OR TABLE_TYPE='VIEW'
UNION
SELECT SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, 'TVF' FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE = 'FUNCTION' AND DATA_TYPE = 'TABLE'";
const string COLUMN_SQL = @"SELECT T.[Database] ,
T.Owner ,
T.TableName ,
T.ColumnName ,
T.OrdinalPosition ,
T.DefaultSetting ,
T.IsNullable ,
T.DataType ,
T.MaxLength ,
T.DatePrecision ,
T.IsIdentity ,
T.IsComputed FROM (
SELECT
TABLE_CATALOG AS [Database],
TABLE_SCHEMA AS Owner,
TABLE_NAME AS TableName,
COLUMN_NAME AS ColumnName,
ORDINAL_POSITION AS OrdinalPosition,
COLUMN_DEFAULT AS DefaultSetting,
IS_NULLABLE AS IsNullable, DATA_TYPE AS DataType,
CHARACTER_MAXIMUM_LENGTH AS MaxLength,
DATETIME_PRECISION AS DatePrecision,
COLUMNPROPERTY(object_id('[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']'), COLUMN_NAME, 'IsIdentity') AS IsIdentity,
COLUMNPROPERTY(object_id('[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']'), COLUMN_NAME, 'IsComputed') as IsComputed
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME=@tableName AND TABLE_SCHEMA=@schemaName
--ORDER BY OrdinalPosition ASC
UNION
SELECT TABLE_CATALOG AS [Database],
TABLE_SCHEMA AS Owner,
TABLE_NAME AS TableName,
COLUMN_NAME AS ColumnName,
ORDINAL_POSITION AS OrdinalPosition,
COLUMN_DEFAULT AS DefaultSetting,
IS_NULLABLE AS IsNullable, DATA_TYPE AS DataType,
CHARACTER_MAXIMUM_LENGTH AS MaxLength,
DATETIME_PRECISION AS DatePrecision,
COLUMNPROPERTY(object_id('[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']'), COLUMN_NAME, 'IsIdentity') AS IsIdentity,
COLUMNPROPERTY(object_id('[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']'), COLUMN_NAME, 'IsComputed') as IsComputed
FROM INFORMATION_SCHEMA.ROUTINE_COLUMNS
WHERE TABLE_NAME=@tableName AND TABLE_SCHEMA=@schemaName
) T
ORDER BY T.OrdinalPosition ASC";
const string FOREIGN_KEYS_SQL =
@"SELECT DISTINCT
tableWithForeignKey.name AS TableWithForeignKey,
columnWithForeignKey.name AS ForeignKeyColumn,
referencedTable.name AS TargetTable,
referencedColumn.name AS TargetTableKey
FROM sys.foreign_key_columns foreignKeyColumn
INNER JOIN sys.tables tableWithForeignKey ON tableWithForeignKey.object_id = foreignKeyColumn.parent_object_id
INNER JOIN sys.columns columnWithForeignKey ON columnWithForeignKey.object_id = foreignKeyColumn.parent_object_id
AND columnWithForeignKey.column_id = foreignKeyColumn.parent_column_id
INNER JOIN sys.tables referencedTable ON referencedTable.object_id = foreignKeyColumn.referenced_object_id
INNER JOIN sys.columns referencedColumn ON referencedColumn.object_id = foreignKeyColumn.referenced_object_id
AND referencedColumn.column_id = foreignKeyColumn.referenced_column_id";
const string SP_NAMES_SQL = @"SELECT o.name AS sp_name, s.name AS schema_name
FROM sys.objects o
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE o.type = 'P'
AND o.name NOT IN ( 'fn_diagramobjects', 'sp_alterdiagram',
'sp_creatediagram', 'sp_dropdiagram',
'sp_helpdiagramdefinition', 'sp_helpdiagrams',
'sp_renamediagram', 'sp_upgraddiagrams',
'sysdiagrams' )";
const string SP_PARAMETERS_SQL = @"SELECT * from information_schema.PARAMETERS
where SPECIFIC_NAME = @spname
order by ORDINAL_POSITION";
}
class SqlServerCeSchemaReader : SchemaReader
{
// SchemaReader.ReadSchema
public override Tables ReadSchema(DbConnection connection, DbProviderFactory factory)
{
var result = new Tables();
_connection = connection;
_factory = factory;
var cmd = _factory.CreateCommand();
cmd.Connection = connection;
cmd.CommandText = TABLE_SQL;
//pull the tables in a reader
using (cmd)
{
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Table tbl = new Table();
tbl.Name = rdr["TABLE_NAME"].ToString();
tbl.CleanName = CleanUp(tbl.Name);
tbl.ClassName = Inflector.MakeSingular(tbl.CleanName);
tbl.Schema = null;
tbl.IsView = false;
result.Add(tbl);
}
}
}
foreach (var tbl in result)
{
tbl.Columns = LoadColumns(tbl);
// Mark the primary key
string PrimaryKey = GetPK(tbl.Name);
var pkColumn = tbl.Columns.SingleOrDefault(x => x.Name.ToLower().Trim() == PrimaryKey.ToLower().Trim());
if (pkColumn != null)
pkColumn.IsPK = true;
}
return result;
}
public override List<SP> ReadSPList(DbConnection connection, DbProviderFactory factory)
{
return new List<SP>();
}
DbConnection _connection;
DbProviderFactory _factory;
List<Column> LoadColumns(Table tbl)
{
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = COLUMN_SQL;
var p = cmd.CreateParameter();
p.ParameterName = "@tableName";
p.Value = tbl.Name;
cmd.Parameters.Add(p);
var result = new List<Column>();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Column col = new Column();
col.Name = rdr["ColumnName"].ToString();
col.PropertyName = CleanUp(col.Name);
col.PropertyType = GetPropertyType(rdr["DataType"].ToString());
col.Size = GetDatatypeSize(rdr["DataType"].ToString());
col.Precision = GetDatatypePrecision(rdr["DataType"].ToString());
col.IsNullable = rdr["IsNullable"].ToString() == "YES";
col.IsAutoIncrement = rdr["AUTOINC_INCREMENT"] != DBNull.Value;
result.Add(col);
}
}
return result;
}
}
string GetPK(string table)
{
string sql = @"SELECT KCU.COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC
ON KCU.CONSTRAINT_NAME=TC.CONSTRAINT_NAME
WHERE TC.CONSTRAINT_TYPE='PRIMARY KEY'
AND KCU.TABLE_NAME=@tableName";
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = sql;
var p = cmd.CreateParameter();
p.ParameterName = "@tableName";
p.Value = table;
cmd.Parameters.Add(p);
var result = "";
DbDataReader reader = cmd.ExecuteReader();
try
{
if (reader.Read())
{
result = reader[0].ToString();
if (reader.Read())
{
result = "";
}
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
return result;
}
}
string GetPropertyType(string sqlType)
{
string sysType = "string";
switch (sqlType)
{
case "bigint":
sysType = "long";
break;
case "smallint":
sysType = "short";
break;
case "int":
sysType = "int";
break;
case "uniqueidentifier":
sysType = "Guid";
break;
case "smalldatetime":
case "datetime":
case "date":
case "time":
sysType = "DateTime";
break;
case "float":
sysType = "double";
break;
case "real":
sysType = "float";
break;
case "numeric":
case "smallmoney":
case "decimal":
case "money":
sysType = "decimal";
break;
case "tinyint":
sysType = "byte";
break;
case "bit":
sysType = "bool";
break;
case "image":
case "binary":
case "varbinary":
case "timestamp":
sysType = "byte[]";
break;
}
return sysType;
}
const string TABLE_SQL = @"SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='TABLE'";
const string COLUMN_SQL = @"SELECT
TABLE_CATALOG AS [Database],
TABLE_SCHEMA AS Owner,
TABLE_NAME AS TableName,
COLUMN_NAME AS ColumnName,
ORDINAL_POSITION AS OrdinalPosition,
COLUMN_DEFAULT AS DefaultSetting,
IS_NULLABLE AS IsNullable, DATA_TYPE AS DataType,
AUTOINC_INCREMENT,
CHARACTER_MAXIMUM_LENGTH AS MaxLength,
DATETIME_PRECISION AS DatePrecision
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME=@tableName
ORDER BY OrdinalPosition ASC";
}
class PostGreSqlSchemaReader : SchemaReader
{
// SchemaReader.ReadSchema
public override Tables ReadSchema(DbConnection connection, DbProviderFactory factory)
{
var result = new Tables();
_connection = connection;
_factory = factory;
var cmd = _factory.CreateCommand();
cmd.Connection = connection;
cmd.CommandText = TABLE_SQL;
//pull the tables in a reader
using (cmd)
{
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Table tbl = new Table();
tbl.Name = rdr["table_name"].ToString();
tbl.Schema = rdr["table_schema"].ToString();
tbl.IsView = string.Compare(rdr["table_type"].ToString(), "View", true) == 0;
tbl.CleanName = CleanUp(tbl.Name);
tbl.ClassName = Inflector.MakeSingular(tbl.CleanName);
result.Add(tbl);
}
}
}
foreach (var tbl in result)
{
tbl.Columns = LoadColumns(tbl);
// Mark the primary key
string PrimaryKey = GetPK(tbl.Name);
var pkColumn = tbl.Columns.SingleOrDefault(x => x.Name.ToLower().Trim() == PrimaryKey.ToLower().Trim());
if (pkColumn != null)
pkColumn.IsPK = true;
}
return result;
}
public override List<SP> ReadSPList(DbConnection connection, DbProviderFactory factory)
{
return new List<SP>();
}
DbConnection _connection;
DbProviderFactory _factory;
List<Column> LoadColumns(Table tbl)
{
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = COLUMN_SQL;
var p = cmd.CreateParameter();
p.ParameterName = "@tableName";
p.Value = tbl.Name;
cmd.Parameters.Add(p);
var result = new List<Column>();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Column col = new Column();
col.Name = rdr["column_name"].ToString();
col.PropertyName = CleanUp(col.Name);
col.PropertyType = GetPropertyType(rdr["udt_name"].ToString());
col.Size = GetDatatypeSize(rdr["udt_name"].ToString());
col.Precision = GetDatatypePrecision(rdr["udt_name"].ToString());
col.IsNullable = rdr["is_nullable"].ToString() == "YES";
col.IsAutoIncrement = rdr["column_default"].ToString().StartsWith("nextval(");
result.Add(col);
}
}
return result;
}
}
string GetPK(string table)
{
string sql = @"SELECT kcu.column_name
FROM information_schema.key_column_usage kcu
JOIN information_schema.table_constraints tc
ON kcu.constraint_name=tc.constraint_name
WHERE lower(tc.constraint_type)='primary key'
AND kcu.table_name=@tablename";
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = sql;
var p = cmd.CreateParameter();
p.ParameterName = "@tableName";
p.Value = table;
cmd.Parameters.Add(p);
var result = "";
DbDataReader reader = cmd.ExecuteReader();
try
{
if (reader.Read())
{
result = reader[0].ToString();
if (reader.Read())
{
result = "";
}
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
return result;
}
}
string GetPropertyType(string sqlType)
{
switch (sqlType)
{
case "int8":
case "serial8":
return "long";
case "bool":
return "bool";
case "bytea ":
return "byte[]";
case "float8":
return "double";
case "int4":
case "serial4":
return "int";
case "money ":
return "decimal";
case "numeric":
return "decimal";
case "float4":
return "float";
case "int2":
return "short";
case "time":
case "timetz":
case "timestamp":
case "timestamptz":
case "date":
return "DateTime";
default:
return "string";
}
}
const string TABLE_SQL = @"
SELECT table_name, table_schema, table_type
FROM information_schema.tables
WHERE (table_type='BASE TABLE' OR table_type='VIEW')
AND table_schema NOT IN ('pg_catalog', 'information_schema');
";
const string COLUMN_SQL = @"
SELECT column_name, is_nullable, udt_name, column_default
FROM information_schema.columns
WHERE table_name=@tableName;
";
}
class MySqlSchemaReader : SchemaReader
{
// SchemaReader.ReadSchema
public override Tables ReadSchema(DbConnection connection, DbProviderFactory factory)
{
var result = new Tables();
var cmd = factory.CreateCommand();
cmd.Connection = connection;
cmd.CommandText = TABLE_SQL;
//pull the tables in a reader
using (cmd)
{
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Table tbl = new Table();
tbl.Name = rdr["TABLE_NAME"].ToString();
tbl.Schema = rdr["TABLE_SCHEMA"].ToString();
tbl.IsView = string.Compare(rdr["TABLE_TYPE"].ToString(), "View", true) == 0;
tbl.CleanName = CleanUp(tbl.Name);
tbl.ClassName = Inflector.MakeSingular(tbl.CleanName);
result.Add(tbl);
}
}
}
//this will return everything for the DB
var schema = connection.GetSchema("COLUMNS");
//loop again - but this time pull by table name
foreach (var item in result)
{
item.Columns = new List<Column>();
//pull the columns from the schema
var columns = schema.Select("TABLE_NAME='" + item.Name + "'");
foreach (var row in columns)
{
Column col = new Column();
col.Name = row["COLUMN_NAME"].ToString();
col.PropertyName = CleanUp(col.Name);
col.PropertyType = GetPropertyType(row);
col.Size = GetDatatypeSize(row["DATA_TYPE"].ToString());
col.Precision = GetDatatypePrecision(row["DATA_TYPE"].ToString());
col.IsNullable = row["IS_NULLABLE"].ToString() == "YES";
col.IsPK = row["COLUMN_KEY"].ToString() == "PRI";
col.IsAutoIncrement = row["extra"].ToString().ToLower().IndexOf("auto_increment") >= 0;
item.Columns.Add(col);
}
}
return result;
}
public override List<SP> ReadSPList(DbConnection connection, DbProviderFactory factory)
{
return new List<SP>();
}
static string GetPropertyType(DataRow row)
{
bool bUnsigned = row["COLUMN_TYPE"].ToString().IndexOf("unsigned") >= 0;
string propType = "string";
switch (row["DATA_TYPE"].ToString())
{
case "bigint":
propType = bUnsigned ? "ulong" : "long";
break;
case "int":
propType = bUnsigned ? "uint" : "int";
break;
case "smallint":
propType = bUnsigned ? "ushort" : "short";
break;
case "guid":
propType = "Guid";
break;
case "smalldatetime":
case "date":
case "datetime":
case "timestamp":
propType = "DateTime";
break;
case "float":
propType = "float";
break;
case "double":
propType = "double";
break;
case "numeric":
case "smallmoney":
case "decimal":
case "money":
propType = "decimal";
break;
case "bit":
case "bool":
case "boolean":
propType = "bool";
break;
case "tinyint":
propType = bUnsigned ? "byte" : "sbyte";
break;
case "image":
case "binary":
case "blob":
case "mediumblob":
case "longblob":
case "varbinary":
propType = "byte[]";
break;
}
return propType;
}
const string TABLE_SQL = @"
SELECT *
FROM information_schema.tables
WHERE (table_type='BASE TABLE' OR table_type='VIEW')
";
}
class OracleSchemaReader : SchemaReader
{
// SchemaReader.ReadSchema
public override Tables ReadSchema(DbConnection connection, DbProviderFactory factory)
{
var result = new Tables();
_connection = connection;
_factory = factory;
var cmd = _factory.CreateCommand();
cmd.Connection = connection;
cmd.CommandText = TABLE_SQL;
cmd.GetType().GetProperty("BindByName").SetValue(cmd, true, null);
//pull the tables in a reader
using (cmd)
{
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Table tbl = new Table();
tbl.Name = rdr["TABLE_NAME"].ToString();
tbl.Schema = rdr["TABLE_SCHEMA"].ToString();
tbl.IsView = string.Compare(rdr["TABLE_TYPE"].ToString(), "View", true) == 0;
tbl.CleanName = CleanUp(tbl.Name);
tbl.ClassName = Inflector.MakeSingular(tbl.CleanName);
result.Add(tbl);
}
}
}
foreach (var tbl in result)
{
tbl.Columns = LoadColumns(tbl);
// Mark the primary key
string PrimaryKey = GetPK(tbl.Name);
var pkColumn = tbl.Columns.SingleOrDefault(x => x.Name.ToLower().Trim() == PrimaryKey.ToLower().Trim());
if (pkColumn != null)
pkColumn.IsPK = true;
}
return result;
}
public override List<SP> ReadSPList(DbConnection connection, DbProviderFactory factory)
{
return new List<SP>();
}
DbConnection _connection;
DbProviderFactory _factory;
List<Column> LoadColumns(Table tbl)
{
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = COLUMN_SQL;
cmd.GetType().GetProperty("BindByName").SetValue(cmd, true, null);
var p = cmd.CreateParameter();
p.ParameterName = ":tableName";
p.Value = tbl.Name;
cmd.Parameters.Add(p);
var result = new List<Column>();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Column col = new Column();
col.Name = rdr["ColumnName"].ToString();
col.PropertyName = CleanUp(col.Name);
col.PropertyType = GetPropertyType(rdr["DataType"].ToString(), (rdr["DataType"] == DBNull.Value ? null : rdr["DataType"].ToString()));
col.Size = GetDatatypeSize(rdr["DataType"].ToString());
col.Precision = GetDatatypePrecision(rdr["DataType"].ToString());
col.IsNullable = rdr["IsNullable"].ToString() == "YES";
col.IsAutoIncrement = false;
result.Add(col);
}
}
return result;
}
}
string GetPK(string table)
{
string sql = @"select column_name from USER_CONSTRAINTS uc
inner join USER_CONS_COLUMNS ucc on uc.constraint_name = ucc.constraint_name
where uc.constraint_type = 'P'
and uc.table_name = upper(:tableName)
and ucc.position = 1";
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = sql;
cmd.GetType().GetProperty("BindByName").SetValue(cmd, true, null);
var p = cmd.CreateParameter();
p.ParameterName = ":tableName";
p.Value = table;
cmd.Parameters.Add(p);
var result = "";
DbDataReader reader = cmd.ExecuteReader();
try
{
if (reader.Read())
{
result = reader[0].ToString();
if (reader.Read())
{
result = "";
}
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
return result;
}
}
string GetPropertyType(string sqlType, string dataScale)
{
string sysType = "string";
switch (sqlType.ToLower())
{
case "bigint":
sysType = "long";
break;
case "smallint":
sysType = "short";
break;
case "int":
sysType = "int";
break;
case "uniqueidentifier":
sysType = "Guid";
break;
case "smalldatetime":
case "datetime":
case "date":
sysType = "DateTime";
break;
case "float":
sysType = "double";
break;
case "real":
case "numeric":
case "smallmoney":
case "decimal":
case "money":
case "number":
sysType = "decimal";
break;
case "tinyint":
sysType = "byte";
break;
case "bit":
sysType = "bool";
break;
case "image":
case "binary":
case "varbinary":
case "timestamp":
sysType = "byte[]";
break;
}
if (sqlType == "number" && dataScale == "0")
return "long";
return sysType;
}
const string TABLE_SQL = @"select TABLE_NAME, 'Table' TABLE_TYPE, USER TABLE_SCHEMA
from USER_TABLES
union all
select VIEW_NAME, 'View', USER
from USER_VIEWS";
const string COLUMN_SQL = @"select table_name TableName,
column_name ColumnName,
data_type DataType,
data_scale DataScale,
nullable IsNullable
from USER_TAB_COLS utc
where table_name = :tableName
order by column_id";
}
class SqliteSchemaReader : SchemaReader
{
// SchemaReader.ReadSchema
public override Tables ReadSchema(DbConnection connection, DbProviderFactory factory)
{
var result = new Tables();
_connection = connection;
_factory = factory;
var cmd = _factory.CreateCommand();
cmd.Connection = connection;
cmd.CommandText = TABLE_SQL;
//cmd.GetType().GetProperty("BindByName").SetValue(cmd, true, null);
//pull the tables in a reader
using (cmd)
{
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Table tbl = new Table();
tbl.Name = rdr["name"].ToString();
tbl.Schema = "";
tbl.IsView = string.Compare(rdr["type"].ToString(), "view", true) == 0;
tbl.CleanName = CleanUp(tbl.Name);
tbl.ClassName = Inflector.MakeSingular(tbl.CleanName);
tbl.SQL = rdr["sql"].ToString();
result.Add(tbl);
}
}
}
foreach (var tbl in result)
{
tbl.Columns = LoadColumns(tbl);
tbl.Indices = LoadIndices(tbl.Name);
tbl.FKeys = LoadFKeys(tbl.Name);
}
return result;
}
public override List<SP> ReadSPList(DbConnection connection, DbProviderFactory factory)
{
return new List<SP>();
}
DbConnection _connection;
DbProviderFactory _factory;
List<Column> LoadColumns(Table tbl)
{
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = string.Format(COLUMN_SQL, tbl.Name);
var result = new List<Column>();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Column col = new Column();
col.Name = rdr["name"].ToString();
col.PropertyName = CleanUp(col.Name);
col.PropertyType = GetPropertyType(rdr["type"].ToString(), (rdr["type"] == DBNull.Value ? null : rdr["type"].ToString()));
col.Size = GetDatatypeSize(rdr["type"].ToString());
col.Precision = GetDatatypePrecision(rdr["type"].ToString());
col.IsNullable = rdr["notnull"].ToString() == "0";
col.IsAutoIncrement = false;
col.IsPK = rdr["pk"].ToString() != "0";
if (col.IsPK)
col.IsAutoIncrement = tbl.SQL.ToUpper().Contains("AUTOINCREMENT");
else
col.IsAutoIncrement = false;
col.DefaultValue = rdr["dflt_value"] == DBNull.Value ? null : rdr["dflt_value"].ToString();
result.Add(col);
}
}
return result;
}
}
List<TableIndex> LoadIndices(string tableName)
{
var result = new List<TableIndex>();
using (var cmd1 = _factory.CreateCommand())
{
cmd1.Connection = _connection;
cmd1.CommandText = string.Format(INDEX_SQL, tableName);
using (IDataReader rdr1 = cmd1.ExecuteReader())
{
while (rdr1.Read())
{
TableIndex indx = new TableIndex();
indx.Name = rdr1["name"].ToString();
indx.SQL = rdr1["sql"].ToString();
indx.IndexColumns = new List<IndexColumn>();
indx.IsUnique = indx.SQL.ToUpper().Contains("UNIQUE");
using (var cmd2 = _factory.CreateCommand())
{
cmd2.Connection = _connection;
cmd2.CommandText = string.Format(INDEX_INFO_SQL, indx.Name);
using (IDataReader rdr2 = cmd2.ExecuteReader())
{
while (rdr2.Read())
{
IndexColumn col = new IndexColumn();
col.Name = rdr2["name"].ToString();
indx.IndexColumns.Add(col);
}
}
}
result.Add(indx);
}
}
}
return result;
}
List<FKey> LoadFKeys(string tblName)
{
using (var cmd = _factory.CreateCommand())
{
cmd.Connection = _connection;
cmd.CommandText = string.Format(FKEY_INFO_SQL, tblName);
var result = new List<FKey>();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
FKey key = new FKey();
key.ToTable = rdr["table"].ToString();
key.ToColumn = rdr["to"].ToString();
key.FromColumn = rdr["from"].ToString();
result.Add(key);
}
}
return result;
}
}
string GetPropertyType(string sqlType, string dataScale)
{
string sysType = "string";
switch (sqlType.ToLower())
{
case "integer":
case "int":
case "tinyint":
case "smallint":
case "mediumint":
case "int2":
case "int8":
sysType = "long";
break;
case "bigint":
case "unsigned big int":
sysType = "long";
break;
case "uniqueidentifier":
sysType = "Guid";
break;
case "smalldatetime":
case "datetime":
case "date":
sysType = "DateTime";
break;
case "float":
case "double precision":
case "double":
sysType = "double";
break;
case "real":
case "numeric":
case "smallmoney":
case "decimal":
case "money":
case "number":
sysType = "decimal";
break;
case "bit":
sysType = "bool";
break;
case "image":
case "binary":
case "varbinary":
case "timestamp":
sysType = "byte[]";
break;
}
if (sqlType == "number" && dataScale == "0")
return "long";
return sysType;
}
const string TABLE_SQL = @"SELECT name, type , sql FROM sqlite_master WHERE type IN ('table','view') and name not in ('sqlite_sequence') ";
const string COLUMN_SQL = @"pragma table_info({0})";
const string INDEX_SQL = @"SELECT name , sql FROM sqlite_master WHERE type IN ('index') and lower(tbl_name) = lower('{0}')";
const string INDEX_INFO_SQL = @"pragma index_info({0})";
const string FKEY_INFO_SQL = @"pragma foreign_key_list({0})";
}
/// <summary>
/// Summary for the Inflector class
/// </summary>
public static class Inflector
{
private static readonly List<InflectorRule> _plurals = new List<InflectorRule>();
private static readonly List<InflectorRule> _singulars = new List<InflectorRule>();
private static readonly List<string> _uncountables = new List<string>();
/// <summary>
/// Initializes the <see cref="Inflector"/> class.
/// </summary>
static Inflector()
{
AddPluralRule("$", "s");
AddPluralRule("s$", "s");
AddPluralRule("(ax|test)is$", "$1es");
AddPluralRule("(octop|vir)us$", "$1i");
AddPluralRule("(alias|status)$", "$1es");
AddPluralRule("(bu)s$", "$1ses");
AddPluralRule("(buffal|tomat)o$", "$1oes");
AddPluralRule("([ti])um$", "$1a");
AddPluralRule("sis$", "ses");
AddPluralRule("(?:([^f])fe|([lr])f)$", "$1$2ves");
AddPluralRule("(hive)$", "$1s");
AddPluralRule("([^aeiouy]|qu)y$", "$1ies");
AddPluralRule("(x|ch|ss|sh)$", "$1es");
AddPluralRule("(matr|vert|ind)ix|ex$", "$1ices");
AddPluralRule("([m|l])ouse$", "$1ice");
AddPluralRule("^(ox)$", "$1en");
AddPluralRule("(quiz)$", "$1zes");
AddSingularRule("s$", String.Empty);
AddSingularRule("ss$", "ss");
AddSingularRule("(n)ews$", "$1ews");
AddSingularRule("([ti])a$", "$1um");
AddSingularRule("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$", "$1$2sis");
AddSingularRule("(^analy)ses$", "$1sis");
AddSingularRule("([^f])ves$", "$1fe");
AddSingularRule("(hive)s$", "$1");
AddSingularRule("(tive)s$", "$1");
AddSingularRule("([lr])ves$", "$1f");
AddSingularRule("([^aeiouy]|qu)ies$", "$1y");
AddSingularRule("(s)eries$", "$1eries");
AddSingularRule("(m)ovies$", "$1ovie");
AddSingularRule("(x|ch|ss|sh)es$", "$1");
AddSingularRule("([m|l])ice$", "$1ouse");
AddSingularRule("(bus)es$", "$1");
AddSingularRule("(o)es$", "$1");
AddSingularRule("(shoe)s$", "$1");
AddSingularRule("(cris|ax|test)es$", "$1is");
AddSingularRule("(octop|vir)i$", "$1us");
AddSingularRule("(alias|status)$", "$1");
AddSingularRule("(alias|status)es$", "$1");
AddSingularRule("^(ox)en", "$1");
AddSingularRule("(vert|ind)ices$", "$1ex");
AddSingularRule("(matr)ices$", "$1ix");
AddSingularRule("(quiz)zes$", "$1");
AddIrregularRule("person", "people");
AddIrregularRule("man", "men");
AddIrregularRule("child", "children");
AddIrregularRule("sex", "sexes");
AddIrregularRule("tax", "taxes");
AddIrregularRule("move", "moves");
AddUnknownCountRule("equipment");
AddUnknownCountRule("information");
AddUnknownCountRule("rice");
AddUnknownCountRule("money");
AddUnknownCountRule("species");
AddUnknownCountRule("series");
AddUnknownCountRule("fish");
AddUnknownCountRule("sheep");
}
/// <summary>
/// Adds the irregular rule.
/// </summary>
/// <param name="singular">The singular.</param>
/// <param name="plural">The plural.</param>
private static void AddIrregularRule(string singular, string plural)
{
AddPluralRule(String.Concat("(", singular[0], ")", singular.Substring(1), "$"), String.Concat("$1", plural.Substring(1)));
AddSingularRule(String.Concat("(", plural[0], ")", plural.Substring(1), "$"), String.Concat("$1", singular.Substring(1)));
}
/// <summary>
/// Adds the unknown count rule.
/// </summary>
/// <param name="word">The word.</param>
private static void AddUnknownCountRule(string word)
{
_uncountables.Add(word.ToLower());
}
/// <summary>
/// Adds the plural rule.
/// </summary>
/// <param name="rule">The rule.</param>
/// <param name="replacement">The replacement.</param>
private static void AddPluralRule(string rule, string replacement)
{
_plurals.Add(new InflectorRule(rule, replacement));
}
/// <summary>
/// Adds the singular rule.
/// </summary>
/// <param name="rule">The rule.</param>
/// <param name="replacement">The replacement.</param>
private static void AddSingularRule(string rule, string replacement)
{
_singulars.Add(new InflectorRule(rule, replacement));
}
/// <summary>
/// Makes the plural.
/// </summary>
/// <param name="word">The word.</param>
/// <returns></returns>
public static string MakePlural(string word)
{
return ApplyRules(_plurals, word);
}
/// <summary>
/// Makes the singular.
/// </summary>
/// <param name="word">The word.</param>
/// <returns></returns>
public static string MakeSingular(string word)
{
return ApplyRules(_singulars, word);
}
/// <summary>
/// Applies the rules.
/// </summary>
/// <param name="rules">The rules.</param>
/// <param name="word">The word.</param>
/// <returns></returns>
private static string ApplyRules(IList<InflectorRule> rules, string word)
{
string result = word;
if (!_uncountables.Contains(word.ToLower()))
{
for (int i = rules.Count - 1; i >= 0; i--)
{
string currentPass = rules[i].Apply(word);
if (currentPass != null)
{
result = currentPass;
break;
}
}
}
return result;
}
/// <summary>
/// Converts the string to title case.
/// </summary>
/// <param name="word">The word.</param>
/// <returns></returns>
public static string ToTitleCase(string word)
{
return Regex.Replace(ToHumanCase(AddUnderscores(word)), @"\b([a-z])",
delegate (Match match) { return match.Captures[0].Value.ToUpper(); });
}
/// <summary>
/// Converts the string to human case.
/// </summary>
/// <param name="lowercaseAndUnderscoredWord">The lowercase and underscored word.</param>
/// <returns></returns>
public static string ToHumanCase(string lowercaseAndUnderscoredWord)
{
return MakeInitialCaps(Regex.Replace(lowercaseAndUnderscoredWord, @"_", " "));
}
/// <summary>
/// Adds the underscores.
/// </summary>
/// <param name="pascalCasedWord">The pascal cased word.</param>
/// <returns></returns>
public static string AddUnderscores(string pascalCasedWord)
{
return Regex.Replace(Regex.Replace(Regex.Replace(pascalCasedWord, @"([A-Z]+)([A-Z][a-z])", "$1_$2"), @"([a-z\d])([A-Z])", "$1_$2"), @"[-\s]", "_").ToLower();
}
/// <summary>
/// Makes the initial caps.
/// </summary>
/// <param name="word">The word.</param>
/// <returns></returns>
public static string MakeInitialCaps(string word)
{
return String.Concat(word.Substring(0, 1).ToUpper(), word.Substring(1).ToLower());
}
/// <summary>
/// Makes the initial lower case.
/// </summary>
/// <param name="word">The word.</param>
/// <returns></returns>
public static string MakeInitialLowerCase(string word)
{
return String.Concat(word.Substring(0, 1).ToLower(), word.Substring(1));
}
/// <summary>
/// Determine whether the passed string is numeric, by attempting to parse it to a double
/// </summary>
/// <param name="str">The string to evaluated for numeric conversion</param>
/// <returns>
/// <c>true</c> if the string can be converted to a number; otherwise, <c>false</c>.
/// </returns>
public static bool IsStringNumeric(string str)
{
double result;
return (double.TryParse(str, NumberStyles.Float, NumberFormatInfo.CurrentInfo, out result));
}
/// <summary>
/// Adds the ordinal suffix.
/// </summary>
/// <param name="number">The number.</param>
/// <returns></returns>
public static string AddOrdinalSuffix(string number)
{
if (IsStringNumeric(number))
{
int n = int.Parse(number);
int nMod100 = n % 100;
if (nMod100 >= 11 && nMod100 <= 13)
return String.Concat(number, "th");
switch (n % 10)
{
case 1:
return String.Concat(number, "st");
case 2:
return String.Concat(number, "nd");
case 3:
return String.Concat(number, "rd");
default:
return String.Concat(number, "th");
}
}
return number;
}
/// <summary>
/// Converts the underscores to dashes.
/// </summary>
/// <param name="underscoredWord">The underscored word.</param>
/// <returns></returns>
public static string ConvertUnderscoresToDashes(string underscoredWord)
{
return underscoredWord.Replace('_', '-');
}
#region Nested type: InflectorRule
/// <summary>
/// Summary for the InflectorRule class
/// </summary>
private class InflectorRule
{
/// <summary>
///
/// </summary>
public readonly Regex regex;
/// <summary>
///
/// </summary>
public readonly string replacement;
/// <summary>
/// Initializes a new instance of the <see cref="InflectorRule"/> class.
/// </summary>
/// <param name="regexPattern">The regex pattern.</param>
/// <param name="replacementText">The replacement text.</param>
public InflectorRule(string regexPattern, string replacementText)
{
regex = new Regex(regexPattern, RegexOptions.IgnoreCase);
replacement = replacementText;
}
/// <summary>
/// Applies the specified word.
/// </summary>
/// <param name="word">The word.</param>
/// <returns></returns>
public string Apply(string word)
{
if (!regex.IsMatch(word))
return null;
string replace = regex.Replace(word, replacement);
if (word == word.ToUpper())
replace = replace.ToUpper();
return replace;
}
}
#endregion
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment