Provides the capability for a user to manipulate and test a set of database connection strings and associated details, leveraging the ConnectionStringManager control.
For a list of all members of this type, see MultiConnectionStringManager Members.
System.Object
MarshalByRefObject
Component
Control
ScrollableControl
ContainerControl
UserControl
MultiConnectionStringManager
Public static (Shared in Visual Basic) members of this type are safe for multithreaded operations. Instance members are not guaranteed to be thread-safe.
This control provides a way to easily manage not just one connection string but a set of connection configurations, allowing one-click switching between databases whether they be on the same server, on different servers, or even dissimilar systems (e.g. SQL Server vs. Oracle.)
There are three functional levels to consider to make best use of this control. The developer creates a separate credential form containing this control along with Accept and Cancel buttons; you open this credential form as needed from your main application. The administrative user is typically the one to use this control, He/she uses this control to define connection configurations for different servers, databases, or users, each of which may be either fully-qualified or partially-qualified. Fully-qualified means that every attribute for a given database connection is provided, i.e. a connection string derived from it is complete. Partially-qualified, on the other hand, omits either the password or the user name and the password, providing all the other details. The end user could also use the control directly, depending on your design. Alternately, you may choose to allow the end user only to interact indirectly when partially-qualified configurations are used. In this case, you would use the related ConnectionStringManager to let the user complement the partially-qualified configuration to make it complete. You will see an example of this below.
Let's first look at developing with the control. The basic steps are: (a) Retrieve the persistent configuration list on startup. (b) Provide a way to edit configurations with the control. (c) Store any changes to the configuration list persistently. (d) Retrieve a specific configuration for actually doing work(!). The code sample below shows one approach to implement each of these.
private CredentialForm credentialForm = new CredentialForm();
// Put this in the main application initialization
// to retrieve the persistent configuration list on startup.
credentialForm.LoadConfigList(Properties.Settings.Default.ConfigList);
// Call this to invoke the control as a configuration editor.
// This displays the credential form as a dialog; upon closing it,
// the changes are stored presistently in the user.config file.
private void EditConfigurations()
{
// Set control to display currently selected configuration when it opens.
credentialForm.SelectConfig(currentConfigurationName);
// Open configuration editor.
credentialForm.ShowDialog();
if (!credentialForm.Cancelled)
{
// Persist any changes.
Properties.Settings.Default.ConfigList = credentialForm.RetrieveConfigList();
// In case the configuration in use was edited, refresh it here as needed.
}
}
// Get a handle to the connection details for a selected configuration
// to do some real work.
// Then use the connection string in your application
// via credentialInfo.ConnectionString
ConnectionDetails credentialInfo =
credentialForm.GetConnectionDetails(currentConfigurationName);
The above code references a CredentialForm that you must create. The next code sample shows an actual working example of such a form.
public partial class CredentialForm : Form
{
public CredentialForm()
{
InitializeComponent();
}
private bool cancelled;
public bool Cancelled
{
get { return cancelled; }
}
private void CredentialForm_VisibleChanged(object sender, EventArgs e)
{
if (Visible) { cancelled = true; }
}
private void acceptButton_Click(object sender, EventArgs e)
{
cancelled = false;
multiConnStrMgr.Accept();
Close();
}
private void cancelButton_Click(object sender, EventArgs e)
{
Close();
}
// Display appropriate data on the ConnectionStringManager control.
public void SelectConfig(string configName)
{
multiConnStrMgr.SelectConfig(configName);
}
// Return the details of the specified configuration name.
public ConnectionDetails GetConnectionDetails(string configName)
{
return multiConnStrMgr.GetConnectionDetails(configName);
}
// Load the persistent configuration list into the control for manipulation.
public void LoadConfigList(ConnectionDetailsCollection configList)
{
multiConnStrMgr.LoadConfigList(configList);
}
// Retrieve the updated (Accept) or original (Cancel) list from the control.
public ConnectionDetailsCollection RetrieveConfigList()
{
return multiConnStrMgr.RetrieveConfigList();
}
}
Since the benefit of this control is to allow rapid switching between diverse database configurations, it makes sense to provide an easy selection control such as a ComboBox, a ToolStripDropDownButton, or a dynamically generated menu list. Once the user make a selection from such a control you pass that configuration name to a method similar to SetConnection, shown next, to get a DbConnection for use in your code or just use the connection string however is appropriate to your application.
private DbConnection SetConnection(string configName)
{
ConnectionDetails credentialInfo =
credentialForm.GetConnectionDetails(configName);
string connString = credentialInfo.ConnectionString;
return
credentialInfo.DbType == ConnectionStringManager.DBTypes.Oracle ?
(DbConnection)new OracleConnection(connString)
: credentialInfo.DbType == ConnectionStringManager.DBTypes.SqlServer ?
(DbConnection)new SqlConnection(connString)
: (DbConnection)new OdbcConnection(connString);
}
That is all you need for fully-qualified configurations. If, however, your set of configurations omits the user name or password on one or more configurations, you will need to first identify that condition, then ask the user for the missing items. A simple way to do that is shown in the following Securitize method.
private string Securitize(ConnectionDetails credentialInfo)
{
string config = credentialInfo.ConfigName;
if (credentialInfo.NeedsPassword() || credentialInfo.NeedsUsername())
{
loginForm.Setup(credentialInfo);
loginForm.ShowDialog();
secureConnStringsCache[config] = loginForm.ConnectionString;
return loginForm.ConnectionString;
}
return credentialInfo.ConnectionString;
}
To use Securitize, modify the second line of SetConnection to this:
string connString = Securitize(credentialInfo);
The Securitize method makes use of another simple form (loginForm):
public partial class LoginForm : Form
{
public string ConnectionString
{
get { return connStrManager.ConnectionString; }
}
public LoginForm()
{
InitializeComponent();
}
public void Setup(ConnectionDetails credentialInfo)
{
connStrManager.ControlTitle = credentialInfo.ConfigName;
connStrManager.ConnectionString = credentialInfo.ConnectionString;
connStrManager.DbType = credentialInfo.DbType;
}
private void loginButton_Click(object sender, EventArgs e)
{
connStrManager.Accept();
Close();
}
private void cancelButton_Click(object sender, EventArgs e)
{
Close();
}
}
This class is instrumented with a StructuredTraceSource for diagnostic output. Its key name is MultiConnectionStringManager.
Since CleanCode 0.9.19.
Namespace: CleanCodeControls.Forms
Assembly: CleanCodeControls (in CleanCodeControls.dll)
MultiConnectionStringManager Members | CleanCodeControls.Forms Namespace