Creating a Custom Schema Provider

To create a schema provider, you build a class library with a public class that implements the SchemaExplorer.IDbSchemaProvider interface.

Naming the assembly

CodeSmith Generator only loads schema providers from assemblies whose file name ends with SchemaProvider.dll. The schema providers that ship with Generator also start with SchemaExplorer. (for example, SchemaExplorer.SqlSchemaProvider.dll), and we recommend you follow the same convention, as in SchemaExplorer.CustomSchemaProvider.dll.

Note

Only the file name matters. Your classes don't have to be in the SchemaExplorer namespace.

Creating the project

  1. In Visual Studio, create a C# or Visual Basic Class Library (.NET Framework) project that targets .NET Framework 4.8. This example names it SchemaExplorer.CustomSchemaProvider; any name that ends with SchemaProvider works.
  2. Rename Class1.cs to CustomSchemaProvider.cs, and rename the class to CustomSchemaProvider.

Adding references to Generator

Add references to these two assemblies in the Generator installation folder (for example, C:\Program Files (x86)\CodeSmith\v8.5). For help, see Add or remove references.

Assembly Location
SchemaExplorer.dll AddIns folder
CodeSmith.Core.dll bin folder

Implementing the interfaces

A schema provider can implement two interfaces:

Interface Purpose
SchemaExplorer.IDbSchemaProvider Required. Supplies the schema objects, such as TableSchema and ColumnSchema, that SchemaExplorer exposes to templates.
SchemaExplorer.IDbConnectionStringEditor Optional. Tells Generator that your provider has a connection string designer, and shows it when the user clicks the … button in the Data Source dialog.

Declare the class with both interfaces:

using System;
using System.Data;

namespace SchemaExplorer.CustomSchemaProvider
{
    public class CustomSchemaProvider : SchemaExplorer.IDbSchemaProvider, SchemaExplorer.IDbConnectionStringEditor
    {
    }
}

Then use Visual Studio's Implement interface quick action to generate the members. The result looks like this:

#region Implementation of IDbSchemaProvider

/// <summary>
/// Gets the name of the schema provider (E.G. SqlSchemaProvider).
/// </summary>
public string Name { get; private set; }

/// <summary>
/// Gets the description for the schema provider (E.G. SQL Server Schema Provider).
/// </summary>
public string Description { get; private set; }

/// <summary>
/// Gets the name of the database.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <returns>The name of the database</returns>
public string GetDatabaseName(string connectionString)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets the extended property collection for a given schema object.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="schemaObject">Any type that derives from SchemaObjectBase. (E.G. DatabaseSchema, TableSchema, ColumnSchema, ViewSchema, ViewColumnSchema, IndexSchema, CommandSchema, ParameterSchema, PrimaryKeySchema, TableKeySchema)</param>
/// <returns>An array of ExtendedProperties for a specific SchemaObjectBase.</returns>
public ExtendedProperty[] GetExtendedProperties(string connectionString, SchemaObjectBase schemaObject)
{
    throw new NotImplementedException();
}

/// <summary>
/// Sets the extended properties.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="schemaObject">Any type that derives from SchemaObjectBase. (E.G. DatabaseSchema, TableSchema, ColumnSchema, ViewSchema, ViewColumnSchema, IndexSchema, CommandSchema, ParameterSchema, PrimaryKeySchema, TableKeySchema)</param>
public void SetExtendedProperties(string connectionString, SchemaObjectBase schemaObject)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets all of the tables available in the database.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="database">The database schema.</param>
/// <returns>An array of tables for a specific database.</returns>
public TableSchema[] GetTables(string connectionString, DatabaseSchema database)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets all columns for a given table.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="table">The table schema.</param>
/// <returns>An array of columns for a specific table.</returns>
public ColumnSchema[] GetTableColumns(string connectionString, TableSchema table)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets all the views available for a given database.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="database">The database schema.</param>
/// <returns>An array of views for a specific database.</returns>
public ViewSchema[] GetViews(string connectionString, DatabaseSchema database)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets the columns for a given view.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="view">The view schema.</param>
/// <returns>An array of view columns for a specific view.</returns>
public ViewColumnSchema[] GetViewColumns(string connectionString, ViewSchema view)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets the definition for a given view.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="view">The view schema.</param>
/// <returns>The definition of a view.</returns>
public string GetViewText(string connectionString, ViewSchema view)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets the primary key for a given table.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="table">The table schema.</param>
/// <returns>The primary key for a specific table.</returns>
public PrimaryKeySchema GetTablePrimaryKey(string connectionString, TableSchema table)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets all of the table keys for a given table.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="table">The table schema.</param>
/// <returns>An array of keys for a specific table.</returns>
public TableKeySchema[] GetTableKeys(string connectionString, TableSchema table)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets all of the indexes for a given table.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="table">The table schema.</param>
/// <returns>An array of indexes for a specific table.</returns>
public IndexSchema[] GetTableIndexes(string connectionString, TableSchema table)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets the data from the given table.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="table">The table schema.</param>
/// <returns>A DataTable containing the data of the specific table.</returns>
public DataTable GetTableData(string connectionString, TableSchema table)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets the data from a given view.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="view">The view schema.</param>
/// <returns>A DataTable containing the data of the specific view.</returns>
public DataTable GetViewData(string connectionString, ViewSchema view)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets all commands for the given database.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="database">The database schema.</param>
/// <returns>An array of commands.</returns>
public CommandSchema[] GetCommands(string connectionString, DatabaseSchema database)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets the parameters for a given command.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="command">The command schema.</param>
/// <returns>An array of parameters.</returns>
public ParameterSchema[] GetCommandParameters(string connectionString, CommandSchema command)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets the definition for a given command.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="command">The command schema.</param>
/// <returns>The definition of a command.</returns>
public string GetCommandText(string connectionString, CommandSchema command)
{
    throw new NotImplementedException();
}

/// <summary>
/// Gets schema information about the results of a given command.
/// </summary>
/// <param name="connectionString">The connection string used to connect to the target database.</param>
/// <param name="command">The command schema.</param>
/// <returns>An array of command results.</returns>
public CommandResultSchema[] GetCommandResultSchemas(string connectionString, CommandSchema command)
{
    throw new NotImplementedException();
}

#endregion

#region Implementation of IDbConnectionStringEditor

public bool ShowEditor(string currentConnectionString)
{
    throw new NotImplementedException();
}

public string ConnectionString { get; private set; }
public bool EditorAvailable { get; private set; }

#endregion

Filling in the implementation

Implement all of the generated methods and properties. The extended property methods (GetExtendedProperties and SetExtendedProperties) are recommended but not required.

Start with the Name and Description properties. Generator shows them when users pick a provider type for a data source:

/// <summary>
/// Gets the name of the schema provider (E.G. SqlSchemaProvider).
/// </summary>
public string Name { get { return "CustomSchemaProvider"; } }

/// <summary>
/// Gets the description for the schema provider (E.G. SQL Server Schema Provider).
/// </summary>
public string Description { get { return "A Custom Schema Provider"; } }

Then implement the methods that read your data source:

Method Returns
GetDatabaseName The name of the database the connection string points to, such as a database name or a file name.
GetTables, GetViews, GetCommands The tables, views and commands in the database.
GetTableColumns, GetViewColumns, GetCommandParameters The columns of a table or view, and the parameters of a command.
GetTablePrimaryKey, GetTableKeys, GetTableIndexes The primary key, keys and indexes of a table.
GetViewText, GetCommandText The definition of a view or command.
GetTableData, GetViewData The data in a table or view, as a DataTable.
GetCommandResultSchemas Schema information about the result sets a command returns.

If your provider has no connection string designer, return false from EditorAvailable and ShowEditor, and an empty string from ConnectionString. Users then type the connection string themselves.

Next step

Build the schema provider into Generator's SchemaProviders folder.