petapoco是个基于T4模板的轻量级ORM,好用效率高,具体介绍略了

获取注释基本原理是调用数据库::fn_listextendedproperty函数,获取扩展属性MS_Description

technet参考资料:sys.fn_listextendedproperty (Transact-SQL)

直接上代码

首先是PetaPoco.Core.ttinclude

106行原始:

...
public string SequenceName;
public bool Ignore;
...

新建Description字段,这个是表的注释

...
public string SequenceName;
public bool Ignore;
public string Description;
...

140行原始:

...
public bool IsAutoIncrement;
public bool Ignore;
...

新建Description字段,这个是列的注释

...
public bool IsAutoIncrement;
public bool Ignore;
public string Description;
...

517行SqlServerSchemaReader.ReadSchema方法,原始:

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

修改后,调用函数获取表的注释:

...
foreach (var tbl in result)
{
using(var cmdDesc=_factory.CreateCommand())
{
cmdDesc.Connection=connection;
cmdDesc.CommandText=TABLE_DESC_SQL; DbParameter p = null; p = cmdDesc.CreateParameter();
p.ParameterName = "@schema";
p.Value=tbl.Schema;
cmdDesc.Parameters.Add(p); p = cmdDesc.CreateParameter();
p.ParameterName = "@table";
p.Value=tbl.Name;
cmdDesc.Parameters.Add(p); using (var rdrDesc=cmdDesc.ExecuteReader())
{
if(rdrDesc.Read())
tbl.Description=rdrDesc["value"].ToString();
}
}
...

572行插入新的代码,获取每一列的注释:

...
foreach (var col in result)
{
using(var cmdDesc=_factory.CreateCommand())
{
cmdDesc.Connection=_connection;
cmdDesc.CommandText=COLUMN_DESC_SQL; DbParameter pDesc = null; pDesc = cmdDesc.CreateParameter();
pDesc.ParameterName = "@schema";
pDesc.Value=tbl.Schema;
cmdDesc.Parameters.Add(pDesc); pDesc = cmdDesc.CreateParameter();
pDesc.ParameterName = "@table";
pDesc.Value=tbl.Name;
cmdDesc.Parameters.Add(pDesc); pDesc = cmdDesc.CreateParameter();
pDesc.ParameterName = "@column";
pDesc.Value=col.Name;
cmdDesc.Parameters.Add(pDesc);
using (var rdrDesc=cmdDesc.ExecuteReader())
{
if(rdrDesc.Read())
col.Description=rdrDesc["value"].ToString();
}
}
}
...

672行插入新的代码,存储调用函数的sql语句:

...
const string TABLE_DESC_SQL=@"SELECT value FROM ::fn_listextendedproperty('MS_Description', 'user', @schema, 'table', @table, null, null)";
const string COLUMN_DESC_SQL=@"SELECT value FROM ::fn_listextendedproperty('MS_Description', 'user', @schema, 'table', @table, 'column', @column)";
...

附完整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 string Description; 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)==);
} 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 string Description;
} public class Tables : List<Table>
{
public Tables()
{
} public Table GetTable(string tableName)
{
return this.Single(x=>string.Compare(x.Name, tableName, true)==);
} 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[]) || 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>)
{
connectionStringName = connSection.ConnectionStrings[connSection.ConnectionStrings.Count-].Name;
result=connSection.ConnectionStrings[connSection.ConnectionStrings.Count-].ConnectionString;
providerName=connSection.ConnectionStrings[connSection.ConnectionStrings.Count-].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();
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-; i>=; i--)
{
if (SchemaName!=null && string.Compare(result[i].Schema, SchemaName, true)!=)
{
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; //pull the tables in a reader
using(var cmd=_factory.CreateCommand())
{
cmd.Connection=connection;
cmd.CommandText=TABLE_SQL;
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)==;
tbl.CleanName=CleanUp(tbl.Name);
tbl.ClassName=Inflector.MakeSingular(tbl.CleanName);
result.Add(tbl);
}
}
}
foreach (var tbl in result)
{
using(var cmdDesc=_factory.CreateCommand())
{
cmdDesc.Connection=connection;
cmdDesc.CommandText=TABLE_DESC_SQL; DbParameter p = null; p = cmdDesc.CreateParameter();
p.ParameterName = "@schema";
p.Value=tbl.Schema;
cmdDesc.Parameters.Add(p); p = cmdDesc.CreateParameter();
p.ParameterName = "@table";
p.Value=tbl.Name;
cmdDesc.Parameters.Add(p); using (var rdrDesc=cmdDesc.ExecuteReader())
{
if(rdrDesc.Read())
tbl.Description=rdrDesc["value"].ToString();
}
} 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"])== ||
(!DBNull.Value.Equals(rdr["DefaultSetting"]) && ((string)rdr["DefaultSetting"] == "(newsequentialid())" ||
(string)rdr["DefaultSetting"] == "(newid())"));
result.Add(col);
}
}
foreach (var col in result)
{
using(var cmdDesc=_factory.CreateCommand())
{
cmdDesc.Connection=_connection;
cmdDesc.CommandText=COLUMN_DESC_SQL; DbParameter pDesc = null; pDesc = cmdDesc.CreateParameter();
pDesc.ParameterName = "@schema";
pDesc.Value=tbl.Schema;
cmdDesc.Parameters.Add(pDesc); pDesc = cmdDesc.CreateParameter();
pDesc.ParameterName = "@table";
pDesc.Value=tbl.Name;
cmdDesc.Parameters.Add(pDesc); pDesc = cmdDesc.CreateParameter();
pDesc.ParameterName = "@column";
pDesc.Value=col.Name;
cmdDesc.Parameters.Add(pDesc);
using (var rdrDesc=cmdDesc.ExecuteReader())
{
if(rdrDesc.Read())
col.Description=rdrDesc["value"].ToString();
}
}
}
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 TABLE_DESC_SQL=@"SELECT value FROM ::fn_listextendedproperty('MS_Description', 'user', @schema, 'table', @table, null, null)"; 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"; const string COLUMN_DESC_SQL=@"SELECT value FROM ::fn_listextendedproperty('MS_Description', 'user', @schema, 'table', @table, 'column', @column)";
} 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)==;
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)==;
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")>=; item.Columns.Add(col);
}
} return result; } static string GetPropertyType(DataRow row)
{
bool bUnsigned = row["COLUMN_TYPE"].ToString().IndexOf("unsigned")>=;
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, -, 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)==;
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, -, 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, -, 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 == "")
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[], ")", singular.Substring(), "$"), String.Concat("$1", plural.Substring()));
AddSingularRule(String.Concat("(", plural[], ")", plural.Substring(), "$"), String.Concat("$1", singular.Substring()));
} /// <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 - ; i >= ; 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[].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(, ).ToUpper(), word.Substring().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(, ).ToLower(), word.Substring());
} /// <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 % ; if (nMod100 >= && nMod100 <= )
return String.Concat(number, "th"); switch (n % ) {
case :
return String.Concat(number, "st");
case :
return String.Concat(number, "nd");
case :
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.Core.ttinclude

至此已经从数据库获取到了注释,下面需要将注释插入到T4模板中

修改PetaPoco.Generator.ttinclude

141行原始:

...
<# if (GeneratePocos) { #>
<#
foreach(Table tbl in from t in tables where !t.Ignore select t)
{
#> <# if (string.IsNullOrEmpty(tbl.Schema)) { #>
[TableName("<#=tbl.Name#>")]
...

添加表的Description注释:

...
<# if (GeneratePocos) { #>
<#
foreach(Table tbl in from t in tables where !t.Ignore select t)
{
#>
/// <summary>
/// <#=tbl.Description??""#>
/// </summary> <# if (string.IsNullOrEmpty(tbl.Schema)) { #>
[TableName("<#=tbl.Name#>")]
...

167行原始:

...
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) { #>
...

添加列的Description注释:

...
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
#>
/// <summary>
/// <#=col.Description??""#>
/// </summary> <# if (TrackModifiedColumns) { #>
...

这样就改完了,打开database.tt按ctrl+s就能更新获取到的注释了

另外GetInstance居然不是单例方法,这简直没法忍,果断改掉:

PetaPoco.Generator.ttinclude,38行修改为:

...
public static <#=RepoName#> GetInstance()
{
if (_instance!=null)
return _instance; if (Factory!=null)
return Factory.GetInstance();
//else
// return new <#=RepoName#>();
return _instance = new <#=RepoName#>();
}
...

petapoco-SQLServer模型增加注释的更多相关文章

  1. SQLSERVER 对于非dbo的表增加注释

    平时我们创建表的时候总是dbo.imsi_collect_state,但是有时候为了方便管理我们可能会创建架构wifi,那么表名就是wifi.imsi_collect_state 原来增加注释的方式是 ...

  2. OpenCV混合高斯模型函数注释说明

    OpenCV混合高斯模型函数注释说明 一.cvaux.h #define CV_BGFG_MOG_MAX_NGAUSSIANS 500 //高斯背景检测算法的默认参数设置 #define CV_BGF ...

  3. 基于PyTorch的Seq2Seq翻译模型详细注释介绍(一)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qysh123/article/detai ...

  4. source insight增加注释宏

    打开base项目,下main.c文件里加入以下代码 对于在一行内的局部注释, 没有找到解除注释的宏, macro Comments_orUn_gx() { //用杠星注释多行,或取消杠星注释 ,不选中 ...

  5. 让Hibernate生成的DDL脚本自动增加注释

    我们知道可以通过Hibernate对象自动生成DDL建表语句,通过PowerDesigner工具可以反向工程生成数据字典,但是在生成的DDL中一直不能写上中文的注释,这就使我们生成的数据字典不具有可用 ...

  6. Power Designer逆向工程导入Oracle表,转为模型加注释

    1.打开PowerDesigner ——文件——Reverse Engineer——DataBase 2.选择所要连接数据库版本,此处使用的是oracle version 11g. 3.点击红色区域, ...

  7. 知方可补不足~powerDesign为模型添加注释(让生成的SQL有注释)

    事实上powerDesign本身就有这个功能,不需要我们修改它的生成器了,这种方法够简单! 一 打开表模型,选择column标签

  8. 【转】在sqlserver下增加MYSQL的链接服务器,实现分布式数据库开发第一步

    首先要在SQLserver上服务器上这装ODBC对mysql的支持,我下载了mysql-connector-odbc-5.1.5-win32.rar,安装后在ODBC中有了DRIVER={MySQL ...

  9. PowerDesigner 怎么给 Table Properties 增加注释和默认值

    1.  选中表,右键 2. 选中“comment”, 这个就是列的注释 3.还是这个页面 ,往下有个“default value”, 这个就是你设置的默认值. 4. 这个是怎么设置默认值.

随机推荐

  1. C#接口的使用场合,接口应用

    当一个项目不断的扩大的时候,会面临的问题是不断的有以下情况: 1.以前编写程序的人离职了,新来的程序员看不懂以前的程序,或者觉得以前的程序部够好,但又不希望删除: 2.当实现第三方接口时,如:读写IC ...

  2. android studio 翻译插件

    插件下载地址 https://github.com/Skykai521/ECTranslation/releases 使用说明: http://gold.xitu.io/entry/573d8d92a ...

  3. android 抓包 使用 tcpdmp + Wireshark

         下载地址tcpdump: http://www.androidtcpdump.com/      使用su用户, 给/system/可写的权限 mount -o remount,rw -t ...

  4. asihttprequest本机调试时正常,发布后闪退

    "Compile sources" -->"Build Phases" 找到ASIFormDataRequest.m和ASIHTTPRequest.m,修 ...

  5. PHP 常用获取路径代码

    <? //获取当前的域名: echo $_SERVER['SERVER_NAME']; //获取来源网址,即点击来到本页的上页网址 echo $_SERVER["HTTP_REFERE ...

  6. JavaScript中的setMonth()方法的小问题 解决:setMonth(month, 1)

    今天测试人员发现一个问题,从英文日期转化中文日期,月份总会有“6月”变为“7月”.于是我在本地反复测试,发现如下规律:只要setMonth()的参数为小于31天的月份时就会变为下一个月. 原因是:因为 ...

  7. CISA 信息系统审计知识点 [第一章. 信息系统审计过程 ]

    对有志成为审计师或者IT管理者de朋友, 第一章. 信息系统审计过程 1. IS 审计和保障标准.指南.工具.职业道德规范 信息技术保证框架(ITAF,Information Technology A ...

  8. js/jquery 实时监听输入框值变化的完美方案:oninput & onpropertychange

    (1)     先说jquery, 使用 jQuery 库的话,只需要同时绑定 oninput 和 onpropertychange 两个事件就可以了,示例代码: $('#username').bin ...

  9. led显字风扇原理?

    神奇的是上面的图案居然会变,十分好奇,求告知原理?? 其实就是依靠转速计算出LED灯变化的频率.这点和老式CRT的显示原理差不多.比如说风扇的转速时60rpm就是每分钟60圈,每秒1圈(当然实际转速快 ...

  10. [转]SharePoint开发中可能用到的各种Context(上下文)

    SharePoint是一个B/S结构的产品,所以在开发过程中会使用到各种各样的上下文(Context)信息,借此机会来总结一下.特别是Javascript的Ctx非常实用,这里记录一下! 一.Http ...