PetaPoco的T4模板优化改进

1 篇文章 0 订阅

主要修改Database.tt这个文件

优化点:

1.修改默认参数;

2.修改实体类名成为首字母大写的驼峰式写法,自动去掉下划线;

3.修改字段为首字母大写的驼峰式写法,自动去掉下划线;


Database.tt

<#@ include file="PetaPoco.Core.ttinclude" #>
<#
	// Settings
    ConnectionStringName = "Patenthr";			// Uses last connection string in config if not specified
    Namespace = "PocoOrm";
    RepoName = "PocoDB";
    GenerateOperations = true;
	GeneratePocos = true;
	GenerateCommon = true;
	ClassPrefix = "";
	ClassSuffix = "";
	TrackModifiedColumns = true;
	ExplicitColumns = true;
	ExcludePrefix = new string[] {"_"}; // Exclude tables by prefix.

    // Read schema
	var tables = LoadTables();


/*
	// Tweak Schema
	tables["tablename"].Ignore = true;							// To ignore a table
	tables["tablename"].ClassName = "newname";					// To change the class name of a table
	tables["tablename"]["columnname"].Ignore = true;			// To ignore a column
	tables["tablename"]["columnname"].PropertyName="newname";	// To change the property name of a column
	tables["tablename"]["columnname"].PropertyType="bool";		// To change the property type of a column
*/

	foreach(Table tbl in from t in tables select t)
	{

		//处理表名称
		string srcStr = tbl.Name.ToLower();
        string newString = "";
        int first = 0;
        while (srcStr.IndexOf("_") != -1)
        {
            first = srcStr.IndexOf("_");
            if (first != srcStr.Length)
            {
                newString = newString + srcStr.Substring(0, first);
                srcStr = srcStr.Substring(first + 1);
                srcStr = srcStr.Substring(0, 1).ToUpper() + srcStr.Substring(1);
            }
        }
        newString = newString + srcStr;

		tables[tbl.Name].ClassName =ClassPrefix+newString.Substring(0, 1).ToUpper() + newString.Substring(1)+
ClassSuffix
;//处理字段名称foreach(Column col in from c in tbl.Columns select c){if(col.Name.StartsWith("_")){tables[tbl.Name][col.Name].Ignore=true; }string srcStrCol = col.Name.ToLower();string newStringCol = "";int firstCol = 0;while (srcStrCol.IndexOf("_") != -1){firstCol = srcStrCol.IndexOf("_");if (firstCol != srcStrCol.Length){newStringCol = newStringCol + srcStrCol.Substring(0, firstCol);srcStrCol = srcStrCol.Substring(firstCol + 1);srcStrCol = srcStrCol.Substring(0, 1).ToUpper() + srcStrCol.Substring(1);}}newStringCol = newStringCol + srcStrCol;tables[tbl.Name][col.Name].PropertyName=newStringCol.Substring(0, 1).ToUpper() + newStringCol.Substring(1); }}// Generate outputif (tables.Count>0){#><#@ include file="PetaPoco.Generator.ttinclude" #><# } #>



附上另外2个文件:

PetaPoco.Core.ttinclude

<#@ template language="C#v3.5" hostspecific="True" #>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="System.Core.dll" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Configuration" #>
<#@ assembly name="System.Windows.Forms" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Data.Common" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.Configuration" #>
<#@ import namespace="System.Windows.Forms" #>
<#+

/*
 This code is part of the PetaPoco project (http://www.toptensoftware.com/petapoco).
 It is based on the SubSonic T4 templates but has been considerably re-organized and reduced
 
 -----------------------------------------------------------------------------------------

 This template can read minimal schema information from the following databases:

	* SQL Server
	* SQL Server CE
	* MySQL
	* PostGreSQL
	* Oracle

 For connection and provider settings the template will look for the web.config or app.config file of the 
 containing Visual Studio project.  It will not however read DbProvider settings from this file.

 In order to work, the appropriate driver must be registered in the system machine.config file.  If you're
 using Visual Studio 2010 the file you want is here:

	C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config

 After making changes to machine.config you will also need to restart Visual Studio.

 Here's a typical set of entries that might help if you're stuck:

	<system.data>
		<DbProviderFactories>
			<add name="Odbc Data Provider" invariant="System.Data.Odbc" description=".Net Framework Data Provider for Odbc" type="System.Data.Odbc.OdbcFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
			<add name="OleDb Data Provider" invariant="System.Data.OleDb" description=".Net Framework Data Provider for OleDb" type="System.Data.OleDb.OleDbFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
			<add name="OracleClient Data Provider" invariant="System.Data.OracleClient" description=".Net Framework Data Provider for Oracle" type="System.Data.OracleClient.OracleClientFactory, System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
			<add name="SqlClient Data Provider" invariant="System.Data.SqlClient" description=".Net Framework Data Provider for SqlServer" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
			<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.3.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
			<add name="Microsoft SQL Server Compact Data Provider" invariant="System.Data.SqlServerCe.3.5" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=3.5.1.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"/><add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"/>
			<add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql Server" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.11.91, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
		</DbProviderFactories>
	</system.data>

 Also, the providers and their dependencies need to be installed to GAC.  

 Eg; this is how I installed the drivers for PostgreSQL

	 gacutil /i Npgsql.dll
	 gacutil /i Mono.Security.dll

 -----------------------------------------------------------------------------------------
 
 SubSonic - http://subsonicproject.com
 
 The contents of this file are subject to the New BSD
 License (the "License"); you may not use this file
 except in compliance with the License. You may obtain a copy of
 the License at http://www.opensource.org/licenses/bsd-license.php
 
 Software distributed under the License is distributed on an 
 "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 implied. See the License for the specific language governing
 rights and limitations under the License.
*/

string ConnectionStringName = "";
string Namespace = "";
string RepoName = "";
string ClassPrefix = "";
string ClassSuffix = "";
string SchemaName = null;
bool IncludeViews = false;
bool GenerateOperations = false;
bool GenerateCommon = true;
bool GeneratePocos = true;
bool ExplicitColumns = true;
bool TrackModifiedColumns = false;
string[] ExcludePrefix = new string[] {};


public class Table
{
    public List<Column> Columns;	
    public string Name;
	public string Schema;
	public bool IsView;
    public string CleanName;
    public string ClassName;
	public string SequenceName;
	public bool Ignore;

    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 class Column
{
    public string Name;
    public string PropertyName;
    public string PropertyType;
    public bool IsPK;
    public bool IsNullable;
	public bool IsAutoIncrement;
	public bool Ignore;
}

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);
		}
	}

}


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]) || cs_keywords.Contains(str))
		str = "@" + str;
	
    return str;
};

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;
}

string GetConnectionString(ref string connectionStringName, out string providerName)
{
    var _CurrentProject = GetCurrentProject();

	providerName=null;
    
    string result="";
    ExeConfigurationFileMap configFile = new ExeConfigurationFileMap();
    configFile.ExeConfigFilename = GetConfigPath();

    if (string.IsNullOrEmpty(configFile.ExeConfigFilename))
        throw new ArgumentNullException("The project does not contain App.config or Web.config file.");
    
    
    var config = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
    var connSection=config.ConnectionStrings;

    //if the connectionString is empty - which is the defauls
    //look for count-1 - this is the last connection string
    //and takes into account AppServices and LocalSqlServer
    if(string.IsNullOrEmpty(connectionStringName))
    {
        if(connSection.ConnectionStrings.Count>1)
        {
			connectionStringName = connSection.ConnectionStrings[connSection.ConnectionStrings.Count-1].Name;
            result=connSection.ConnectionStrings[connSection.ConnectionStrings.Count-1].ConnectionString;
            providerName=connSection.ConnectionStrings[connSection.ConnectionStrings.Count-1].ProviderName;
        }            
    }
    else
    {
        try
        {
            result=connSection.ConnectionStrings[connectionStringName].ConnectionString;
            providerName=connSection.ConnectionStrings[connectionStringName].ProviderName;
        }
        catch
        {
            result="There is no connection string name called '"+connectionStringName+"'";
        }
    }

//	if (String.IsNullOrEmpty(providerName))
//		providerName="System.Data.SqlClient";
    
    return result;
}

string _connectionString="";
string _providerName="";

void InitConnectionString()
{
    if(String.IsNullOrEmpty(_connectionString))
    {
        _connectionString=GetConnectionString(ref ConnectionStringName, out _providerName);

		if(_connectionString.Contains("|DataDirectory|"))
		{
			//have to replace it
			string dataFilePath=GetDataDirectory();
			_connectionString=_connectionString.Replace("|DataDirectory|",dataFilePath);
		}    
	}
}

public string ConnectionString
{
    get 
    {
		InitConnectionString();
        return _connectionString;
    }
}

public string ProviderName
{
    get 
    {
		InitConnectionString();
        return _providerName;
    }
}

public EnvDTE.Project GetCurrentProject()  {

    IServiceProvider _ServiceProvider = (IServiceProvider)Host;
    if (_ServiceProvider == null)
        throw new Exception("Host property returned unexpected value (null)");
	
    EnvDTE.DTE dte = (EnvDTE.DTE)_ServiceProvider.GetService(typeof(EnvDTE.DTE));
    if (dte == null)
        throw new Exception("Unable to retrieve EnvDTE.DTE");
	
    Array activeSolutionProjects = (Array)dte.ActiveSolutionProjects;
    if (activeSolutionProjects == null)
        throw new Exception("DTE.ActiveSolutionProjects returned null");
	
    EnvDTE.Project dteProject = (EnvDTE.Project)activeSolutionProjects.GetValue(0);
    if (dteProject == null)
        throw new Exception("DTE.ActiveSolutionProjects[0] returned null");
	
    return dteProject;

}

private string GetProjectPath()
{
    EnvDTE.Project project = GetCurrentProject();
    System.IO.FileInfo info = new System.IO.FileInfo(project.FullName);
    return info.Directory.FullName;
}

private string GetConfigPath()
{
    EnvDTE.Project project = GetCurrentProject();
    foreach (EnvDTE.ProjectItem item in project.ProjectItems)
    {
        // if it is the app.config file, then open it up
        if (item.Name.Equals("App.config",StringComparison.InvariantCultureIgnoreCase) || item.Name.Equals("Web.config",StringComparison.InvariantCultureIgnoreCase))
			return GetProjectPath() + "\\" + item.Name;
    }
    return String.Empty;
}

public string GetDataDirectory()
{
    EnvDTE.Project project=GetCurrentProject();
    return System.IO.Path.GetDirectoryName(project.FileName)+"\\App_Data\\";
}

static string zap_password(string connectionString)
{
	var rx = new Regex("password=.*;", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.IgnoreCase);
	return rx.Replace(connectionString, "password=**zapped**;");
}



Tables LoadTables()
{
	InitConnectionString();

	WriteLine("// This file was automatically generated by the PetaPoco T4 Template");
	WriteLine("// Do not make changes directly to this file - edit the template instead");
	WriteLine("// ");
	WriteLine("// The following connection settings were used to generate this file");
	WriteLine("// ");
	WriteLine("//     Connection String Name: `{0}`", ConnectionStringName);
	WriteLine("//     Provider:               `{0}`", ProviderName);
	WriteLine("//     Connection String:      `{0}`", zap_password(ConnectionString));
	WriteLine("//     Schema:                 `{0}`", SchemaName);
	WriteLine("//     Include Views:          `{0}`", IncludeViews);
	WriteLine("");

	DbProviderFactory _factory;
	try
	{
		_factory = DbProviderFactories.GetFactory(ProviderName);
	}
	catch (Exception x)
	{
		var error=x.Message.Replace("\r\n", "\n").Replace("\n", " ");
		Warning(string.Format("Failed to load provider `{0}` - {1}", ProviderName, error));
		WriteLine("");
		WriteLine("// -----------------------------------------------------------------------------------------");
		WriteLine("// Failed to load provider `{0}` - {1}", ProviderName, error);
		WriteLine("// -----------------------------------------------------------------------------------------");
		WriteLine("");
		return new Tables();
	}

	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
			{
				// Assume SQL Server
				reader=new SqlServerSchemaReader();
			}

			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)
				{
					result.RemoveAt(i);
					continue;
				}
				if(StartsWithAny(result[i].ClassName, ExcludePrefix)) {
					result.RemoveAt(i);
					continue;
				}
			}

			conn.Close();


			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)
			{
				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", " ");
		Warning(string.Format("Failed to read database schema - {0}", error));
		WriteLine("");
		WriteLine("// -----------------------------------------------------------------------------------------");
		WriteLine("// Failed to read database schema - {0}", error);
		WriteLine("// -----------------------------------------------------------------------------------------");
		WriteLine("");
		return new Tables();
	}

        
}

bool StartsWithAny(string s, IEnumerable<string> items)
{
    if (s == null)
        return false;

    return items.Any(i => s.StartsWith(i));
}

abstract class SchemaReader
{
	public abstract Tables ReadSchema(DbConnection connection, DbProviderFactory factory);
	public GeneratedTextTransformation outer;
	public void WriteLine(string o)
	{
		outer.WriteLine(o);
	}

}

class SqlServerSchemaReader : 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;
	}
	
	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.IsNullable=rdr["IsNullable"].ToString()=="YES";
					col.IsAutoIncrement=((int)rdr["IsIdentity"])==1 || 
							(!DBNull.Value.Equals(rdr["DefaultSetting"]) && ((string)rdr["DefaultSetting"] == "(newsequentialid())" ||
							(string)rdr["DefaultSetting"] == "(newid())"));
					result.Add(col);
				}
			}

			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=cmd.ExecuteScalar();

			if(result!=null)
				return result.ToString();    
		}	         
		
		return "";
	}
	
	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 "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'
		ORDER BY TABLE_SCHEMA,TABLE_TYPE,TABLE_NAME";

	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, 
			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";
	  
}

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;
	}
	
	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.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=cmd.ExecuteScalar();

			if(result!=null)
				return result.ToString();    
		}	         
		
		return "";
	}
	
	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;
	}
	
	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.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=cmd.ExecuteScalar();

			if(result!=null)
				return result.ToString();    
		}	         
		
		return "";
	}
	
	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";

			case "uuid":
				return "Guid";

			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.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;
	
	}

	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') AND TABLE_SCHEMA=DATABASE()
			";

}

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);
		cmd.GetType().GetProperty("InitialLONGFetchSize").SetValue(cmd, -1, 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;
	}
	
	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);
			cmd.GetType().GetProperty("InitialLONGFetchSize").SetValue(cmd, -1, 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["DataScale"] == DBNull.Value ? null : rdr["DataScale"].ToString()));
					col.IsNullable = "YES".Equals(rdr["isnullable"].ToString()) || "Y".Equals(rdr["isnullable"].ToString());
					col.IsAutoIncrement=true;
					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);
			cmd.GetType().GetProperty("InitialLONGFetchSize").SetValue(cmd, -1, null);

			var p = cmd.CreateParameter();
			p.ParameterName = ":tableName";
			p.Value=table;
			cmd.Parameters.Add(p);

			var result=cmd.ExecuteScalar();

			if(result!=null)
				return result.ToString();    
		}	         
		
		return "";
	}
	
	string GetPropertyType(string sqlType, string dataScale)
	{
		string sysType="string";
		sqlType = sqlType.ToLower();
		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":
				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
 and virtual_column = 'NO'
 order by column_id";
	  
}




/// <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
}

#>

PetaPoco.Generator.ttinclude

<#

if (string.IsNullOrEmpty(Namespace)) Namespace=ConnectionStringName;
if (string.IsNullOrEmpty(RepoName) && !string.IsNullOrEmpty(ConnectionStringName)) RepoName=ConnectionStringName + "DB";
if (string.IsNullOrEmpty(Namespace)) Namespace="PetaPoco";
if (string.IsNullOrEmpty(RepoName)) RepoName="PetaPocoDB";

#>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using PetaPoco;

namespace <#=Namespace #>
{
<# if (GenerateCommon) { #>
	public partial class <#=RepoName#> : Database
	{
		public <#=RepoName#>() 
			: base("<#=ConnectionStringName#>")
		{
			CommonConstruct();
		}

		public <#=RepoName#>(string connectionStringName) 
			: base(connectionStringName)
		{
			CommonConstruct();
		}
		
		partial void CommonConstruct();
		
		public interface IFactory
		{
			<#=RepoName#> GetInstance();
		}
		
		public static IFactory Factory { get; set; }
        public static <#=RepoName#> GetInstance()
        {
			if (_instance!=null)
				return _instance;
				
			if (Factory!=null)
				return Factory.GetInstance();
			else
				return new <#=RepoName#>();
        }

		[ThreadStatic] static <#=RepoName#> _instance;
		
		public override void OnBeginTransaction()
		{
			if (_instance==null)
				_instance=this;
		}
		
		public override void OnEndTransaction()
		{
			if (_instance==this)
				_instance=null;
		}
        
<# if (GenerateOperations) { #>
		public class Record<T> where T:new()
		{
			public static <#=RepoName#> repo { get { return <#=RepoName#>.GetInstance(); } }
			public bool IsNew() { return repo.IsNew(this); }
			public object Insert() { return repo.Insert(this); }
<# if (!TrackModifiedColumns) { #>
			public void Save() { repo.Save(this); }
			public int Update() { return repo.Update(this); }
<# } #>
			public int Update(IEnumerable<string> columns) { return repo.Update(this, columns); }
			public static int Update(string sql, params object[] args) { return repo.Update<T>(sql, args); }
			public static int Update(Sql sql) { return repo.Update<T>(sql); }
			public int Delete() { return repo.Delete(this); }
			public static int Delete(string sql, params object[] args) { return repo.Delete<T>(sql, args); }
			public static int Delete(Sql sql) { return repo.Delete<T>(sql); }
			public static int Delete(object primaryKey) { return repo.Delete<T>(primaryKey); }
			public static bool Exists(object primaryKey) { return repo.Exists<T>(primaryKey); }
			public static bool Exists(string sql, params object[] args) { return repo.Exists<T>(sql, args); }
			public static T SingleOrDefault(object primaryKey) { return repo.SingleOrDefault<T>(primaryKey); }
			public static T SingleOrDefault(string sql, params object[] args) { return repo.SingleOrDefault<T>(sql, args); }
			public static T SingleOrDefault(Sql sql) { return repo.SingleOrDefault<T>(sql); }
			public static T FirstOrDefault(string sql, params object[] args) { return repo.FirstOrDefault<T>(sql, args); }
			public static T FirstOrDefault(Sql sql) { return repo.FirstOrDefault<T>(sql); }
			public static T Single(object primaryKey) { return repo.Single<T>(primaryKey); }
			public static T Single(string sql, params object[] args) { return repo.Single<T>(sql, args); }
			public static T Single(Sql sql) { return repo.Single<T>(sql); }
			public static T First(string sql, params object[] args) { return repo.First<T>(sql, args); }
			public static T First(Sql sql) { return repo.First<T>(sql); }
			public static List<T> Fetch(string sql, params object[] args) { return repo.Fetch<T>(sql, args); }
			public static List<T> Fetch(Sql sql) { return repo.Fetch<T>(sql); }
			public static List<T> Fetch(long page, long itemsPerPage, string sql, params object[] args) { return repo.Fetch<T>(page, itemsPerPage, sql, args); }
			public static List<T> Fetch(long page, long itemsPerPage, Sql sql) { return repo.Fetch<T>(page, itemsPerPage, sql); }
			public static List<T> SkipTake(long skip, long take, string sql, params object[] args) { return repo.SkipTake<T>(skip, take, sql, args); }
			public static List<T> SkipTake(long skip, long take, Sql sql) { return repo.SkipTake<T>(skip, take, sql); }
			public static Page<T> Page(long page, long itemsPerPage, string sql, params object[] args) { return repo.Page<T>(page, itemsPerPage, sql, args); }
			public static Page<T> Page(long page, long itemsPerPage, Sql sql) { return repo.Page<T>(page, itemsPerPage, sql); }
			public static IEnumerable<T> Query(string sql, params object[] args) { return repo.Query<T>(sql, args); }
			public static IEnumerable<T> Query(Sql sql) { return repo.Query<T>(sql); }
<# if (TrackModifiedColumns) { #>			
			private Dictionary<string,bool> ModifiedColumns;
			private void OnLoaded()
			{
				ModifiedColumns = new Dictionary<string,bool>();
			}
			protected void MarkColumnModified(string column_name)
			{
				if (ModifiedColumns!=null)
					ModifiedColumns[column_name]=true;
			}
			public int Update() 
			{ 
				if (ModifiedColumns==null)
					return repo.Update(this); 

				int retv = repo.Update(this, ModifiedColumns.Keys);
				ModifiedColumns.Clear();
				return retv;
			}
			public void Save() 
			{ 
				if (repo.IsNew(this))
					repo.Insert(this);
				else
					Update();
			}
<# } #>
		}
<# } #>
	}
<# } #>	

<# if (GeneratePocos) { #>
<#
foreach(Table tbl in from t in tables where !t.Ignore select t)
{
#>
    
<# if (string.IsNullOrEmpty(tbl.Schema)) { #>	[TableName("<#=tbl.Name#>")]<# } else { #>	[TableName("<#=tbl.Schema + "." + tbl.Name#>")]<# } #>
<# if (tbl.PK!=null && tbl.PK.IsAutoIncrement) { #><# if (tbl.SequenceName==null) { #>	[PrimaryKey("<#=tbl.PK.Name#>")]<# } else { #>	[PrimaryKey("<#=tbl.PK.Name#>", sequenceName="<#=tbl.SequenceName#>")]<# } #><# } #>
<# if (tbl.PK!=null && !tbl.PK.IsAutoIncrement) { #>[PrimaryKey("<#=tbl.PK.Name#>", AutoIncrement=false)]<# } #>
<# if (ExplicitColumns) { #>		[ExplicitColumns]<# } #>
    public partial class <#=tbl.ClassName#> <# if (GenerateOperations) { #>: <#=RepoName#>.Record<<#=tbl.ClassName#>> <# } #> 
    {

<#
foreach(Column col in from c in tbl.Columns where !c.Ignore select c)
{
		// Column bindings	
#>

<# if (TrackModifiedColumns) { #>
<# if (col.Name!=col.PropertyName) { #>		[Column("<#=col.Name #>")] <# } else { #><# if (ExplicitColumns) { #>		[Column] <# } #> <# } #>
		public <#=col.PropertyType #><#=CheckNullable(col)#> <#=col.PropertyName #> 
		{
			get
			{
				return _<#=col.PropertyName #>;
			}
			set
			{
				_<#=col.PropertyName #> = value;
				MarkColumnModified("<#=col.Name#>");
			}
		}
		<#=col.PropertyType #><#=CheckNullable(col)#> _<#=col.PropertyName #>;
<# } else { #>
<# if (col.Name!=col.PropertyName) { #>
		[Column("<#=col.Name#>")] 
		public <#=col.PropertyType #><#=CheckNullable(col)#> <#=col.PropertyName #> { get; set; }
<# } else { #><# if (ExplicitColumns) { #>		[Column] <# } #>
		public <#=col.PropertyType #><#=CheckNullable(col)#> <#=col.PropertyName #> { get; set; }
<# } #>
<# } #>
<# } #>
	}
<# } #>
<# } #>
}



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值