Discover Tables and Columns
These scenarios demonstrate how to list the tables and columns in an unknown database.
Scenario Prototype
public interface IDiscoverTablesAndColumnsScenario
{
IList<string> ListColumnsInTable(string schemaName, string tableName);
IList<string> ListColumnsInView(string schemaName, string viewName);
IList<string> ListTables();
IList<string> ListViews();
}
ADO.NET
The SQL needed to list tables, views, and columns is database-specific.
- DB2: Catalog Tables
- MySQL: Information Schema
- Oracle: Information Schema
- PostgreSQL: Information Schema
- SQL Server: System Views or Information Schema
While most databases expose Information Schema (e.g. INFORMATION_SCHEMA.TABLES
), the column names may vary from vendor to vendor.
public class DiscoverTablesAndColumnsScenario : SqlServerScenarioBase, IDiscoverTablesAndColumnsScenario
{
public DiscoverTablesAndColumnsScenario(string connectionString) : base(connectionString)
{ }
public IList<string> ListColumnsInTable(string schemaName, string tableName)
{
const string sql =
@"SELECT c.name FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE s.name = @SchemaName AND t.name = @TableName";
var result = new List<string>();
using (var con = OpenConnection())
using (var cmd = new SqlCommand(sql, con))
{
cmd.Parameters.AddWithValue("@SchemaName", schemaName);
cmd.Parameters.AddWithValue("@TableName", tableName);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
result.Add(reader.GetString(0));
}
}
return result;
}
public IList<string> ListColumnsInView(string schemaName, string viewName)
{
const string sql =
@"SELECT c.name FROM sys.columns c
INNER JOIN sys.views v ON c.object_id = v.object_id
INNER JOIN sys.schemas s ON v.schema_id = s.schema_id
WHERE s.name = @SchemaName AND v.name = @ViewName";
var result = new List<string>();
using (var con = OpenConnection())
using (var cmd = new SqlCommand(sql, con))
{
cmd.Parameters.AddWithValue("@SchemaName", schemaName);
cmd.Parameters.AddWithValue("@ViewName", viewName);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
result.Add(reader.GetString(0));
}
}
return result;
}
public IList<string> ListTables()
{
const string sql =
"SELECT s.name + '.' + t.name FROM sys.tables t INNER JOIN sys.schemas s ON t.schema_id = s.schema_id";
var result = new List<string>();
using (var con = OpenConnection())
using (var cmd = new SqlCommand(sql, con))
{
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
result.Add(reader.GetString(0));
}
}
return result;
}
public IList<string> ListViews()
{
const string sql =
"SELECT s.name + '.' + v.name FROM sys.views v INNER JOIN sys.schemas s ON v.schema_id = s.schema_id";
var result = new List<string>();
using (var con = OpenConnection())
using (var cmd = new SqlCommand(sql, con))
{
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
result.Add(reader.GetString(0));
}
}
return result;
}
}
Chain
Chain exposes information about the database via the DatabaseMetadata
property. If you don't use the Preload
method, only tables and views previously seen will be available.
public class DiscoverTablesAndColumnsScenario : IDiscoverTablesAndColumnsScenario
{
readonly SqlServerDataSource m_DataSource;
public DiscoverTablesAndColumnsScenario(SqlServerDataSource dataSource)
{
m_DataSource = dataSource;
}
public IList<string> ListColumnsInTable(string schemaName, string tableName)
{
return m_DataSource.DatabaseMetadata.GetTableOrView(schemaName + "." + tableName)
.Columns.Select(c => c.SqlName).ToList();
}
public IList<string> ListColumnsInView(string schemaName, string viewName)
{
return m_DataSource.DatabaseMetadata.GetTableOrView(schemaName + "." + viewName)
.Columns.Select(c => c.SqlName).ToList();
}
public IList<string> ListTables()
{
m_DataSource.DatabaseMetadata.PreloadTables(); //Only need to call this once
return m_DataSource.DatabaseMetadata.GetTablesAndViews().Where(t => t.IsTable)
.Select(t => t.Name.ToString()).ToList();
}
public IList<string> ListViews()
{
m_DataSource.DatabaseMetadata.PreloadViews(); //Only need to call this once
return m_DataSource.DatabaseMetadata.GetTablesAndViews().Where(t => t.IsTable == false)
.Select(t => t.Name.ToString()).ToList();
}
}
Dapper
The SQL needed to list tables, views, and columns is database-specific. See the ADO.NET example above for links to the documentation.
public class DiscoverTablesAndColumnsScenario : ScenarioBase, IDiscoverTablesAndColumnsScenario
{
public DiscoverTablesAndColumnsScenario(string connectionString) : base(connectionString)
{ }
public IList<string> ListColumnsInTable(string schemaName, string tableName)
{
const string sql =
@"SELECT c.name FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE s.name = @SchemaName AND t.name = @TableName";
using (var con = OpenConnection())
return con.Query<string>(sql, new { schemaName, tableName }).ToList();
}
public IList<string> ListColumnsInView(string schemaName, string viewName)
{
const string sql =
@"SELECT c.name FROM sys.columns c
INNER JOIN sys.views v ON c.object_id = v.object_id
INNER JOIN sys.schemas s ON v.schema_id = s.schema_id
WHERE s.name = @SchemaName AND v.name = @ViewName";
using (var con = OpenConnection())
return con.Query<string>(sql, new { schemaName, viewName }).ToList();
}
public IList<string> ListTables()
{
const string sql =
"SELECT s.name + '.' + t.name FROM sys.tables t INNER JOIN sys.schemas s ON t.schema_id = s.schema_id";
using (var con = OpenConnection())
return con.Query<string>(sql).ToList();
}
public IList<string> ListViews()
{
const string sql =
"SELECT s.name + '.' + v.name FROM sys.views v INNER JOIN sys.schemas s ON v.schema_id = s.schema_id";
using (var con = OpenConnection())
return con.Query<string>(sql).ToList();
}
}
DbConnector
TODO
Entity Framework 6
TODO
Entity Framework Core
The SQL needed to list tables, views, and columns is database-specific. See the ADO.NET example above for links to the documentation.
public class DiscoverTablesAndColumnsScenario : IDiscoverTablesAndColumnsScenario
{
private readonly Func<OrmCookbookContext> CreateDbContext;
public DiscoverTablesAndColumnsScenario(Func<OrmCookbookContext> dBContextFactory)
{
CreateDbContext = dBContextFactory;
}
public IList<string> ListColumnsInTable(string schemaName, string tableName)
{
using OrmCookbookContext context = CreateDbContext();
using DbCommand commnd = context.Database.GetDbConnection().CreateCommand();
const string sql =
@"SELECT c.name AS ColumnName
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE s.name = @SchemaName AND t.name = @TableName";
commnd.CommandText = sql;
commnd.Parameters.Add(new SqlParameter { ParameterName = "SchemaName", DbType = DbType.String, Value = schemaName });
commnd.Parameters.Add(new SqlParameter { ParameterName = "TableName", DbType = DbType.String, Value = tableName });
commnd.Connection!.Open();
DbDataReader reader = commnd.ExecuteReader(CommandBehavior.CloseConnection);
var columnNames = new List<string>();
while (reader.Read())
{
int columnNameOrdinal = reader.GetOrdinal("ColumnName");
string columnName = reader.GetString(columnNameOrdinal);
columnNames.Add(columnName);
}
return columnNames;
}
public IList<string> ListColumnsInView(string schemaName, string viewName)
{
using OrmCookbookContext context = CreateDbContext();
using DbCommand commnd = context.Database.GetDbConnection().CreateCommand();
const string sql =
@"SELECT c.name AS ColumnName
FROM sys.columns c
INNER JOIN sys.views v ON c.object_id = v.object_id
INNER JOIN sys.schemas s ON v.schema_id = s.schema_id
WHERE s.name = @SchemaName AND v.name = @ViewName";
commnd.CommandText = sql;
commnd.Parameters.Add(new SqlParameter { ParameterName = "SchemaName", DbType = DbType.String, Value = schemaName });
commnd.Parameters.Add(new SqlParameter { ParameterName = "ViewName", DbType = DbType.String, Value = viewName });
commnd.Connection!.Open();
DbDataReader reader = commnd.ExecuteReader(CommandBehavior.CloseConnection);
var columnNames = new List<string>();
while (reader.Read())
{
int columnNameOrdinal = reader.GetOrdinal("ColumnName");
string columnName = reader.GetString(columnNameOrdinal);
columnNames.Add(columnName);
}
return columnNames;
}
public IList<string> ListTables()
{
using OrmCookbookContext context = CreateDbContext();
using DbCommand commnd = context.Database.GetDbConnection().CreateCommand();
const string sql =
@"SELECT s.name + '.' + t.name AS TableName
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id";
commnd.CommandText = sql;
commnd.Connection!.Open();
DbDataReader reader = commnd.ExecuteReader(CommandBehavior.CloseConnection);
var tableNames = new List<string>();
while (reader.Read())
{
int tableNameOrdinal = reader.GetOrdinal("TableName");
string tableName = reader.GetString(tableNameOrdinal);
tableNames.Add(tableName);
}
return tableNames;
}
public IList<string> ListViews()
{
using OrmCookbookContext context = CreateDbContext();
using DbCommand commnd = context.Database.GetDbConnection().CreateCommand();
const string sql =
@"SELECT s.name + '.' + v.name AS ViewName
FROM sys.views v
INNER JOIN sys.schemas s ON v.schema_id = s.schema_id";
commnd.CommandText = sql;
commnd.Connection!.Open();
DbDataReader reader = commnd.ExecuteReader(CommandBehavior.CloseConnection);
var tableNames = new List<string>();
while (reader.Read())
{
int tableNameOrdinal = reader.GetOrdinal("ViewName");
string tableName = reader.GetString(tableNameOrdinal);
tableNames.Add(tableName);
}
return tableNames;
}
}
LINQ to DB
public class DiscoverTablesAndColumnsScenario : IDiscoverTablesAndColumnsScenario
{
public IList<string> ListColumnsInTable(string schemaName, string tableName)
{
using (var db = new OrmCookbook())
{
var dbSchema = db.DataProvider.GetSchemaProvider().GetSchema(db,
new GetSchemaOptions()
{
IncludedSchemas = new[] { schemaName },
GetForeignKeys = false,
GetProcedures = false,
GetTables = true,
LoadTable = (t) => t.Schema == schemaName && t.Name == tableName
});
return dbSchema.Tables.Single().Columns.Select(c => c.ColumnName).ToList();
}
}
public IList<string> ListColumnsInView(string schemaName, string viewName)
{
using (var db = new OrmCookbook())
{
var dbSchema = db.DataProvider.GetSchemaProvider().GetSchema(db,
new GetSchemaOptions()
{
IncludedSchemas = new[] { schemaName },
GetForeignKeys = false,
GetProcedures = false,
GetTables = true,
LoadTable = (t) => t.Schema == schemaName && t.Name == viewName
});
return dbSchema.Tables.Single().Columns.Select(c => c.ColumnName).ToList();
}
}
public IList<string> ListTables()
{
using (var db = new OrmCookbook())
{
var dbSchema = db.DataProvider.GetSchemaProvider().GetSchema(db,
new GetSchemaOptions()
{
GetForeignKeys = false,
GetProcedures = false,
GetTables = true,
LoadTable = (t) => !t.IsView
});
return dbSchema.Tables.Select(t => t.SchemaName + "." + t.TableName).ToList();
}
}
public IList<string> ListViews()
{
using (var db = new OrmCookbook())
{
var dbSchema = db.DataProvider.GetSchemaProvider().GetSchema(db,
new GetSchemaOptions()
{
GetForeignKeys = false,
GetProcedures = false,
GetTables = true,
LoadTable = (t) => t.IsView
});
return dbSchema.Tables.Select(t => t.SchemaName + "." + t.TableName).ToList();
}
}
}
LLBLGen Pro
TODO
NHibernate
TODO
RepoDb
TODO
ServiceStack
TODO