Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@troyanov
Last active March 7, 2020 09:22
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save troyanov/5883752 to your computer and use it in GitHub Desktop.
Save troyanov/5883752 to your computer and use it in GitHub Desktop.
Generate Enums from database lookup tables. CoreAutomation.tt - t4 helper class, that uses EnvDTE to get all Projects in Solution, configurations, etc. DBEnum.tt - generates enums for tables by criteria enumDescriptionColumnName
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output encoding="utf-8" extension=".cs"#>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="EnvDTE80" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Configuration" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Configuration" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="EnvDTE80" #>
<#+
public class CoreAutomation
{
private readonly DTE _dte;
public CoreAutomation(IServiceProvider host)
{
_dte = (DTE)host.GetService(typeof(DTE));
}
/// <summary>
/// Provides access to the host project.
/// </summary>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/envdte.project.aspx
/// </remarks>
public Project CurrentProject
{
get
{
return (Project)((Array)_dte.ActiveSolutionProjects).GetValue(0);
}
}
/// <summary>
/// Provides access to the host solution.
/// </summary>
public Solution Solution
{
get { return _dte.Solution; }
}
/// <summary>
/// Provides access to the hosts solution startup project.
/// </summary>
public Project StartUpProject
{
get
{
var startupProjectName = ((Array)_dte.Solution.SolutionBuild.StartupProjects).GetValue(0).ToString();
var projects = Projects();
foreach (var project in projects)
{
// returns object typeof(Project), not just project name
if (project.UniqueName == startupProjectName)
return project;
}
return null;
}
}
/// <summary>
/// Provides access to the application/web configuration file.
/// </summary>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/system.configuration.configuration.aspx
/// </remarks>
public System.Configuration.Configuration Configuration(Project project)
{
string configurationFilename = null;
foreach (ProjectItem item in project.ProjectItems)
{
if (!Regex.IsMatch(item.Name, "(app|web).config", RegexOptions.IgnoreCase))
continue;
configurationFilename = item.FileNames[0];
break;
}
if(!string.IsNullOrEmpty(configurationFilename))
{
var configFile = new ExeConfigurationFileMap {ExeConfigFilename = configurationFilename};
return System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
}
return null;
}
/// <summary>
/// Returns all Projects in Solution
/// </summary>
public IList<Project> Projects()
{
var projects = _dte.Solution.Projects;
var list = new List<Project>();
var item = projects.GetEnumerator();
while (item.MoveNext())
{
var project = item.Current as Project;
if (project == null)
{
continue;
}
if (project.Kind == ProjectKinds.vsProjectKindSolutionFolder)
{
list.AddRange(GetSolutionFolderProjects(project));
}
else
{
list.Add(project);
}
}
return list;
}
private IEnumerable<Project> GetSolutionFolderProjects(Project solutionFolder)
{
var list = new List<Project>();
for (var i = 1; i <= solutionFolder.ProjectItems.Count; i++)
{
var subProject = solutionFolder.ProjectItems.Item(i).SubProject;
if (subProject == null)
{
continue;
}
// If this is another solution folder, do a recursive call, otherwise add
if (subProject.Kind == ProjectKinds.vsProjectKindSolutionFolder)
{
list.AddRange(GetSolutionFolderProjects(subProject));
}
else
{
list.Add(subProject);
}
}
return list;
}
}
#>
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output encoding="utf-8" extension=".cs"#>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ include file="CoreAutomation.tt" #>
<#@ import namespace="System.Data.Entity.Design.PluralizationServices" #>
<#@ import namespace="System.Data.SqlClient" #>
<#
// instantiate CoreAutomation
var coreAutomation = new CoreAutomation((IServiceProvider)this.Host);
// get startup project for our solution
var startupProject = coreAutomation.StartUpProject;
var connectionStrings = coreAutomation.Configuration(startupProject).ConnectionStrings.ConnectionStrings;
string connectionString = null;
// Release or Debug?
var configuration = coreAutomation.Solution.SolutionBuild.ActiveConfiguration.Name;
switch (configuration)
{
case "Debug":
connectionString = connectionStrings["development"].ConnectionString;
break;
case "Release":
connectionString = connectionStrings["production"].ConnectionString;
break;
}
// System.Diagnostics.Debug.WriteLine(connectionString); - you can view it with Dbgview.exe from SysInternals
// enum value column name:
const string enumDescriptionColumnName = "EnumDescription";
// enum namespace
const string enumNameSpace = "MyNamespace.Enums";
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
var codeGenerationTools = new CodeGenerationTools(this);
// open ADO connection
if (connectionString != null)
{
var connection = new SqlConnection(connectionString);
var command = connection.CreateCommand();
connection.Open();
command.CommandText = string.Format(@"select distinct t.name
from sys.tables as t
inner join sys.columns as c on t.object_id = c.object_id
and c.name = '{0}'", enumDescriptionColumnName);
var tableReader = command.ExecuteReader();
var enumTables = new List<string>();
while (tableReader.Read())
{
enumTables.Add(tableReader["name"].ToString());
}
connection.Close();
foreach (var tableName in enumTables)
{
connection.Open();
// get the enum name
var enumName = PluralizationService.CreateService(new CultureInfo("en-US")).Singularize(tableName);
fileManager.StartNewFile(enumName + ".cs");
WriteLine("namespace " + enumNameSpace);
ClearIndent();
WriteLine("{");
PushIndent(" ");
WriteLine("public enum " + enumName);
WriteLine("{");
ClearIndent();
command.CommandText = string.Format("select * from {0}", codeGenerationTools.Escape(tableName));
var columnReader = command.ExecuteReader();
var values = new Dictionary<string, string>();
while (columnReader.Read())
{
// Fill only the values that the field "enumDescriptionColumnName" have value
if (!string.IsNullOrEmpty(columnReader[enumDescriptionColumnName].ToString().Trim()))
{
values.Add(columnReader[enumDescriptionColumnName].ToString().Trim().Replace(" ",""),
columnReader[0].ToString().Trim().Replace(" ",""));
}
}
foreach (var entry in values)
{
PushIndent(" ");
PushIndent(" ");
WriteLine(entry.Key + " = " + entry.Value + ",");
ClearIndent();
}
PushIndent(" ");
WriteLine("}");
ClearIndent();
WriteLine("}");
connection.Close();
}
fileManager.Process();
}
#>
@RobertBonham
Copy link

Thank you for putting this out on Gist. The code itself did what I wanted, but more importantly for me, it's a great T4 example to learn and build on. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment