diff --git a/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ConnectionStringDefinitionDialog.Designer.cs b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ConnectionStringDefinitionDialog.Designer.cs new file mode 100644 index 0000000000..757a491845 --- /dev/null +++ b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ConnectionStringDefinitionDialog.Designer.cs @@ -0,0 +1,239 @@ +/* + * Responsibilities:<br> + * <br> + * Collaboration:<br> + * <br> + * User: ${USER} + * Date: ${DATE} + * Time: ${TIME} + * + */ +namespace SharpDbTools.Forms +{ + partial class ConnectionStringDefinitionDialog : System.Windows.Forms.Form + { + /// <summary> + /// Designer variable used to keep track of non-visual components. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Disposes resources used by the form. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// <summary> + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.connStringPropertyGrid = new System.Windows.Forms.PropertyGrid(); + this.buttonsFlowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel(); + this.testButton = new System.Windows.Forms.Button(); + this.submitButton = new System.Windows.Forms.Button(); + this.cancelButton = new System.Windows.Forms.Button(); + this.providerTypeComboBox = new System.Windows.Forms.ComboBox(); + this.dataSourceTypeLabel = new System.Windows.Forms.Label(); + this.connStringResult = new System.Windows.Forms.TextBox(); + this.connectionStringLabel = new System.Windows.Forms.Label(); + this.progressTimer = new System.Windows.Forms.Timer(this.components); + this.statusStrip = new System.Windows.Forms.StatusStrip(); + this.outputMessageTabControl = new System.Windows.Forms.TabControl(); + this.connectionStringTab = new System.Windows.Forms.TabPage(); + this.testResultTab = new System.Windows.Forms.TabPage(); + this.testResultTextBox = new System.Windows.Forms.TextBox(); + this.buttonsFlowLayoutPanel.SuspendLayout(); + this.outputMessageTabControl.SuspendLayout(); + this.connectionStringTab.SuspendLayout(); + this.testResultTab.SuspendLayout(); + this.SuspendLayout(); + // + // connStringPropertyGrid + // + this.connStringPropertyGrid.Location = new System.Drawing.Point(0, 39); + this.connStringPropertyGrid.Name = "connStringPropertyGrid"; + this.connStringPropertyGrid.Size = new System.Drawing.Size(547, 300); + this.connStringPropertyGrid.TabIndex = 0; + // + // buttonsFlowLayoutPanel + // + this.buttonsFlowLayoutPanel.Controls.Add(this.testButton); + this.buttonsFlowLayoutPanel.Controls.Add(this.submitButton); + this.buttonsFlowLayoutPanel.Controls.Add(this.cancelButton); + this.buttonsFlowLayoutPanel.Location = new System.Drawing.Point(3, 447); + this.buttonsFlowLayoutPanel.Name = "buttonsFlowLayoutPanel"; + this.buttonsFlowLayoutPanel.Size = new System.Drawing.Size(312, 34); + this.buttonsFlowLayoutPanel.TabIndex = 1; + // + // testButton + // + this.testButton.Location = new System.Drawing.Point(3, 3); + this.testButton.Name = "testButton"; + this.testButton.Size = new System.Drawing.Size(75, 23); + this.testButton.TabIndex = 0; + this.testButton.Text = "Test"; + this.testButton.UseVisualStyleBackColor = true; + this.testButton.Click += new System.EventHandler(this.TestButtonClick); + // + // submitButton + // + this.submitButton.Location = new System.Drawing.Point(84, 3); + this.submitButton.Name = "submitButton"; + this.submitButton.Size = new System.Drawing.Size(75, 23); + this.submitButton.TabIndex = 1; + this.submitButton.Text = "Submit"; + this.submitButton.UseVisualStyleBackColor = true; + this.submitButton.Click += new System.EventHandler(this.SubmitButtonClick); + // + // cancelButton + // + this.cancelButton.Location = new System.Drawing.Point(165, 3); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(75, 23); + this.cancelButton.TabIndex = 2; + this.cancelButton.Text = "Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.CancelButtonClick); + // + // providerTypeComboBox + // + this.providerTypeComboBox.FormattingEnabled = true; + this.providerTypeComboBox.Location = new System.Drawing.Point(117, 12); + this.providerTypeComboBox.Name = "providerTypeComboBox"; + this.providerTypeComboBox.Size = new System.Drawing.Size(195, 21); + this.providerTypeComboBox.TabIndex = 2; + this.providerTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.ProviderTypeSelectedIndexChanged); + // + // dataSourceTypeLabel + // + this.dataSourceTypeLabel.Location = new System.Drawing.Point(3, 9); + this.dataSourceTypeLabel.Name = "dataSourceTypeLabel"; + this.dataSourceTypeLabel.Size = new System.Drawing.Size(108, 23); + this.dataSourceTypeLabel.TabIndex = 3; + this.dataSourceTypeLabel.Text = "Data Source Type:"; + this.dataSourceTypeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // connStringResult + // + this.connStringResult.Enabled = false; + this.connStringResult.Location = new System.Drawing.Point(0, 0); + this.connStringResult.Multiline = true; + this.connStringResult.Name = "connStringResult"; + this.connStringResult.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.connStringResult.Size = new System.Drawing.Size(413, 74); + this.connStringResult.TabIndex = 4; + // + // connectionStringLabel + // + this.connectionStringLabel.Location = new System.Drawing.Point(12, 348); + this.connectionStringLabel.Name = "connectionStringLabel"; + this.connectionStringLabel.Size = new System.Drawing.Size(100, 23); + this.connectionStringLabel.TabIndex = 5; + this.connectionStringLabel.Text = "Connection String:"; + // + // progressTimer + // + this.progressTimer.Interval = 1000; + this.progressTimer.Tick += new System.EventHandler(this.ProgressTimerTick); + // + // statusStrip + // + this.statusStrip.Location = new System.Drawing.Point(0, 478); + this.statusStrip.Name = "statusStrip"; + this.statusStrip.Size = new System.Drawing.Size(547, 22); + this.statusStrip.TabIndex = 6; + this.statusStrip.Text = "statusStrip1"; + // + // testResultTab + // + this.outputMessageTabControl.Controls.Add(this.connectionStringTab); + this.outputMessageTabControl.Controls.Add(this.testResultTab); + this.outputMessageTabControl.Location = new System.Drawing.Point(118, 345); + this.outputMessageTabControl.Name = "testResultTab"; + this.outputMessageTabControl.SelectedIndex = 0; + this.outputMessageTabControl.Size = new System.Drawing.Size(417, 100); + this.outputMessageTabControl.TabIndex = 7; + // + // tabPage1 + // + this.connectionStringTab.Controls.Add(this.connStringResult); + this.connectionStringTab.Location = new System.Drawing.Point(4, 22); + this.connectionStringTab.Name = "tabPage1"; + this.connectionStringTab.Padding = new System.Windows.Forms.Padding(3); + this.connectionStringTab.Size = new System.Drawing.Size(409, 74); + this.connectionStringTab.TabIndex = 0; + this.connectionStringTab.Text = "Connection String"; + this.connectionStringTab.UseVisualStyleBackColor = true; + // + // tabPage2 + // + this.testResultTab.Controls.Add(this.testResultTextBox); + this.testResultTab.Location = new System.Drawing.Point(4, 22); + this.testResultTab.Name = "tabPage2"; + this.testResultTab.Padding = new System.Windows.Forms.Padding(3); + this.testResultTab.Size = new System.Drawing.Size(409, 74); + this.testResultTab.TabIndex = 1; + this.testResultTab.Text = "Test Result Message"; + this.testResultTab.UseVisualStyleBackColor = true; + // + // testResultTextBox + // + this.testResultTextBox.Location = new System.Drawing.Point(-5, 0); + this.testResultTextBox.Multiline = true; + this.testResultTextBox.Name = "testResultTextBox"; + this.testResultTextBox.Size = new System.Drawing.Size(418, 77); + this.testResultTextBox.TabIndex = 0; + // + // ConnectionStringDefinitionDialog + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(547, 500); + this.Controls.Add(this.outputMessageTabControl); + this.Controls.Add(this.statusStrip); + this.Controls.Add(this.connectionStringLabel); + this.Controls.Add(this.dataSourceTypeLabel); + this.Controls.Add(this.providerTypeComboBox); + this.Controls.Add(this.buttonsFlowLayoutPanel); + this.Controls.Add(this.connStringPropertyGrid); + this.Name = "ConnectionStringDefinitionDialog"; + this.Text = "Set up Connection String"; + this.buttonsFlowLayoutPanel.ResumeLayout(false); + this.outputMessageTabControl.ResumeLayout(false); + this.connectionStringTab.ResumeLayout(false); + this.connectionStringTab.PerformLayout(); + this.testResultTab.ResumeLayout(false); + this.testResultTab.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + } + private System.Windows.Forms.TabControl outputMessageTabControl; + private System.Windows.Forms.TextBox testResultTextBox; + private System.Windows.Forms.TabPage testResultTab; + private System.Windows.Forms.TabPage connectionStringTab; + + private System.Windows.Forms.Timer progressTimer; + private System.Windows.Forms.StatusStrip statusStrip; + private System.Windows.Forms.TextBox connStringResult; + private System.Windows.Forms.Label connectionStringLabel; + private System.Windows.Forms.Label dataSourceTypeLabel; + private System.Windows.Forms.ComboBox providerTypeComboBox; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button submitButton; + private System.Windows.Forms.Button testButton; + private System.Windows.Forms.FlowLayoutPanel buttonsFlowLayoutPanel; + private System.Windows.Forms.PropertyGrid connStringPropertyGrid; + } +} diff --git a/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ConnectionStringDefinitionDialog.cs b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ConnectionStringDefinitionDialog.cs new file mode 100644 index 0000000000..560c9527e6 --- /dev/null +++ b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ConnectionStringDefinitionDialog.cs @@ -0,0 +1,257 @@ +// <file> +// <copyright see="prj:///doc/copyright.txt"/> +// <license see="prj:///doc/license.txt"/> +// <owner name="Dickon Field" email=""/> +// <version>$Revision: 1684 $</version> +// </file> + +using System; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; +using System.Data.Common; +using System.ComponentModel; + +using SharpDbTools.Data; + +namespace SharpDbTools.Forms +{ + /// <summary> + /// This class creates a dialog that can be used to create and test connection strings + /// that can be used with .net 2.0 DbProviders. + /// It utilises .net 2.0 configuration to discover any DbProviderFactories that are + /// installed and configured in machine.config, app.config or user.config using + /// standard .net 2.0 apis. + /// It then enables a user to browse the properties of each type of db connection, + /// set values for them and test the resulting connection string. + /// When the submit button is clicked the dialog is dismissed and the connection + /// string constructed is accessible through the ConnectionString property of the dialog. + /// </summary> + public partial class ConnectionStringDefinitionDialog + { + ToolStripProgressBar connectionTestProgressBar = new ToolStripProgressBar(); + ConnectionTestBackgroundWorker testConnectionBackgroundWorker; + string resultMessage; + string invariantName; + ConnectionTestState connectionTestState = ConnectionTestState.UnTested; + + public ConnectionStringDefinitionDialog() + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + this.connStringPropertyGrid.PropertyValueChanged += + new PropertyValueChangedEventHandler(this.ConnStringAttributesViewPropertyValueChanged); + // add a ProgressBar to the statusString + this.statusStrip.Items.Add(connectionTestProgressBar); + this.connectionTestProgressBar.Step = 10; + this.connectionTestProgressBar.Minimum = 0; + this.connectionTestProgressBar.Maximum = 150; + } + + public string InvariantName { + get { + return this.invariantName; + } + set { + this.invariantName = value; + } + } + + public ConnectionTestState ConnectionTestState { + get { + return this.connectionTestState; + } + } + + public string ResultMessage + { + get + { + return resultMessage; + } + set + { + resultMessage = value; + } + } + + public DbConnectionStringBuilder ConnectionStringBuilder + { + get + { + return (DbConnectionStringBuilder)this.connStringPropertyGrid.SelectedObject; + } + } + + public string ConnectionString + { + get + { + return ((DbConnectionStringBuilder)this.connStringPropertyGrid.SelectedObject).ConnectionString; + } + } + + protected override void OnLoad(EventArgs e) + { + // + // set the PropertyGrid to browse the available DbProviders + // + + base.OnLoad(e); + + DbProvidersService service = DbProvidersService.GetDbProvidersService(); + List<string> names = service.Names; + this.providerTypeComboBox.DataSource = names; + this.connStringResult.Text = this.ConnectionString; + } + + void CancelButtonClick(object sender, System.EventArgs e) + { + this.DialogResult = DialogResult.Cancel; + this.Close(); + } + + void ProviderTypeSelectedIndexChanged(object sender, System.EventArgs e) + { + string selection = (string)this.providerTypeComboBox.SelectedItem; + DbProvidersService service = DbProvidersService.GetDbProvidersService(); + DbProviderFactory factory = service[selection]; + DbConnectionStringBuilder builder = factory.CreateConnectionStringBuilder(); + connStringPropertyGrid.SelectedObject = builder; + } + + void ConnStringAttributesViewPropertyValueChanged(Object s, PropertyValueChangedEventArgs args) + { + // looking for changes to the ConnectionString property in the PropertyGrid + this.connStringResult.Text = this.ConnectionString; + this.outputMessageTabControl.SelectTab(this.connectionStringTab); + ResetTestResultTextBox(); + } + + void TestButtonClick(object sender, System.EventArgs e) + { + string dbTypeName = (string)this.providerTypeComboBox.SelectedItem; + testConnectionBackgroundWorker = new ConnectionTestBackgroundWorker(dbTypeName); + testConnectionBackgroundWorker.WorkerSupportsCancellation = false; + progressTimer.Enabled = true; + testConnectionBackgroundWorker.DoWork += + new DoWorkEventHandler(this.TestConnectionBackgroundWorkerDoWork); + testConnectionBackgroundWorker.RunWorkerCompleted += + new RunWorkerCompletedEventHandler(TestConnectionRunWorkerComplete); + testConnectionBackgroundWorker.RunWorkerAsync(); + } + + void ProgressTimerTick(object sender, System.EventArgs e) + { + this.BeginInvoke(new EventHandler(UpdateProgressBar)); + } + + void UpdateProgressBar(object sender, EventArgs e) + { + ToolStripProgressBar p = connectionTestProgressBar; + if (p.Value == p.Maximum) p.Value = 0; + p.PerformStep(); + } + + void SetTestResultTextBox() + { + this.testResultTextBox.Text = ResultMessage; + this.outputMessageTabControl.SelectTab(this.testResultTab); + } + + void ResetTestResultTextBox() + { + this.testResultTextBox.Text = ""; + this.connectionTestState = ConnectionTestState.UnTested; + } + + void TestConnectionBackgroundWorkerDoWork(object sender, DoWorkEventArgs e) + { + DbConnection connection = null; + try + { + // get the current name + + ConnectionTestBackgroundWorker bw = sender as ConnectionTestBackgroundWorker; + string currentDbTypeName = bw.DatabaseType; + + // get the DbProviderFactory for this name + + DbProvidersService service = DbProvidersService.GetDbProvidersService(); + DbProviderFactory factory = service[currentDbTypeName]; + + // get a connection object or this factory + + connection = factory.CreateConnection(); + connection.ConnectionString = this.ConnectionString; + + connection.Open(); + e.Result = "Connection Succeeded"; + connectionTestState = ConnectionTestState.TestSucceeded; + } + catch(Exception ex) + { + e.Result = "Connection Failed: " + ex.Message; + connectionTestState = ConnectionTestState.TestFailed; + } + finally + { + if (connection != null) + { + connection.Close(); + } + } + } + + void TestConnectionRunWorkerComplete(object sender, RunWorkerCompletedEventArgs args) + { + ResultMessage = args.Result as string; + this.Invoke(new EventHandler(TestConnectionCompleted)); + } + + void TestConnectionCompleted(object sender, EventArgs args) + { + progressTimer.Enabled = false; + connectionTestProgressBar.Value = 0; + SetTestResultTextBox(); + testConnectionBackgroundWorker.Dispose(); + } + + void SubmitButtonClick(object sender, System.EventArgs e) + { + string name = (string)this.providerTypeComboBox.SelectedItem; + DbProvidersService service = DbProvidersService.GetDbProvidersService(); + this.InvariantName = service.GetInvariantName(name); + + this.DialogResult = DialogResult.OK; + this.Close(); + } + } + + public enum ConnectionTestState + { + UnTested, + TestFailed, + TestSucceeded + } + + class ConnectionTestBackgroundWorker: BackgroundWorker + { + private string dbTypeName; + + public ConnectionTestBackgroundWorker(string dbTypeName): base() + { + this.dbTypeName = dbTypeName; + } + + public string DatabaseType + { + get + { + return dbTypeName; + } + } + } +} diff --git a/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ConnectionStringDefinitionDialog.resx b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ConnectionStringDefinitionDialog.resx new file mode 100644 index 0000000000..157d9061d2 --- /dev/null +++ b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ConnectionStringDefinitionDialog.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="progressTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>247, 17</value> + </metadata> + <metadata name="statusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>371, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/GetConnectionLogicalNameDialog.Designer.cs b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/GetConnectionLogicalNameDialog.Designer.cs new file mode 100644 index 0000000000..bf888294c5 --- /dev/null +++ b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/GetConnectionLogicalNameDialog.Designer.cs @@ -0,0 +1,100 @@ +/* + * User: dickon + * Date: 04/08/2006 + * Time: 22:21 + */ +namespace SharpDbTools.Forms +{ + partial class GetConnectionLogicalNameDialog : System.Windows.Forms.Form + { + /// <summary> + /// Designer variable used to keep track of non-visual components. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Disposes resources used by the form. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// <summary> + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// </summary> + private void InitializeComponent() + { + this.connectionName = new System.Windows.Forms.TextBox(); + this.connectionNameOKButton = new System.Windows.Forms.Button(); + this.connectionNameCancelButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // connectionName + // + this.connectionName.Location = new System.Drawing.Point(12, 33); + this.connectionName.MaxLength = 30; + this.connectionName.Name = "connectionName"; + this.connectionName.Size = new System.Drawing.Size(292, 21); + this.connectionName.TabIndex = 0; + // + // connectionNameOKButton + // + this.connectionNameOKButton.Location = new System.Drawing.Point(66, 70); + this.connectionNameOKButton.Name = "connectionNameOKButton"; + this.connectionNameOKButton.Size = new System.Drawing.Size(75, 23); + this.connectionNameOKButton.TabIndex = 1; + this.connectionNameOKButton.Text = "OK"; + this.connectionNameOKButton.UseVisualStyleBackColor = true; + this.connectionNameOKButton.Click += new System.EventHandler(this.ConnectionNameOKButtonClick); + // + // connectionNameCancelButton + // + this.connectionNameCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.connectionNameCancelButton.Location = new System.Drawing.Point(171, 70); + this.connectionNameCancelButton.Name = "connectionNameCancelButton"; + this.connectionNameCancelButton.Size = new System.Drawing.Size(75, 23); + this.connectionNameCancelButton.TabIndex = 2; + this.connectionNameCancelButton.Text = "Cancel"; + this.connectionNameCancelButton.UseVisualStyleBackColor = true; + this.connectionNameCancelButton.Click += new System.EventHandler(this.ConnectionNameCancelButtonClick); + // + // label1 + // + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(259, 23); + this.label1.TabIndex = 3; + this.label1.Text = "Please provide the name for your db connection:"; + // + // GetConnectionLogicalNameDialog + // + this.AcceptButton = this.connectionNameOKButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.connectionNameCancelButton; + this.ClientSize = new System.Drawing.Size(316, 114); + this.Controls.Add(this.label1); + this.Controls.Add(this.connectionNameCancelButton); + this.Controls.Add(this.connectionNameOKButton); + this.Controls.Add(this.connectionName); + this.Name = "GetConnectionLogicalNameDialog"; + this.Text = "Connection Name"; + this.ResumeLayout(false); + this.PerformLayout(); + } + private System.Windows.Forms.TextBox connectionName; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button connectionNameCancelButton; + private System.Windows.Forms.Button connectionNameOKButton; + } +} diff --git a/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/GetConnectionLogicalNameDialog.cs b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/GetConnectionLogicalNameDialog.cs new file mode 100644 index 0000000000..b485d5180b --- /dev/null +++ b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/GetConnectionLogicalNameDialog.cs @@ -0,0 +1,46 @@ +/* + * User: dickon + * Date: 04/08/2006 + * Time: 22:21 + */ + +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace SharpDbTools.Forms +{ + /// <summary> + /// Description of GetConnectionLogicalNameDialog. + /// </summary> + public partial class GetConnectionLogicalNameDialog + { + public GetConnectionLogicalNameDialog() + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + + // + // TODO: Add constructor code after the InitializeComponent() call. + // + } + + public string LogicalConnectionName { + get { + return this.connectionName.Text; + } + } + + void ConnectionNameOKButtonClick(object sender, System.EventArgs e) + { + this.Close(); + } + + void ConnectionNameCancelButtonClick(object sender, System.EventArgs e) + { + this.Close(); + } + } +} diff --git a/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/GetConnectionLogicalNameDialog.resx b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/GetConnectionLogicalNameDialog.resx new file mode 100644 index 0000000000..7080a7d118 --- /dev/null +++ b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/GetConnectionLogicalNameDialog.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ServerBrowserTool.cs b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ServerBrowserTool.cs new file mode 100644 index 0000000000..2e4b76c179 --- /dev/null +++ b/src/AddIns/Misc/SharpDbTools/Project/Src/Forms/ServerBrowserTool.cs @@ -0,0 +1,454 @@ +// <file> +// <copyright see="prj:///doc/copyright.txt"/> +// <license see="prj:///doc/license.txt"/> +// <owner name="Dickon Field" email=""/> +// <version>$Revision: 1766 $</version> +// </file> + +/* + * User: Dickon Field + * Date: 12/06/2006 + * Time: 06:25 + */ + +using System; +using System.Windows.Forms; +using System.Data; +using System.Data.Common; +using System.Collections.Generic; + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Gui; +using SharpDbTools.Data; + +namespace SharpDbTools.Forms +{ + /// <summary> + /// Enables a user to browse metadata associated with a db server and to open resources + /// referenced therein. The intention is to extend this to other server processes over + /// time. + /// </summary> + public class ServerBrowserTool : AbstractPadContent + { + Panel ctl; + + /// <summary> + /// ServerBrowserTool hosts one or more TreeViews providing views of types + /// of server. Currently it shows only relational database servers. + /// </summary> + public ServerBrowserTool() + { + LoggingService.Debug("Loading ServerBrowserTool"); + ServerToolTreeView dbTree = new ServerToolTreeView(); + dbTree.Dock = DockStyle.Fill; + ctl = new Panel(); + ctl.Controls.Add(dbTree); + } + + /// <summary> + /// The <see cref="System.Windows.Forms.Control"/> representing the pad + /// </summary> + public override Control Control { + get { + return ctl; + } + } + + /// <summary> + /// Rebuildes the pad + /// </summary> + public override void RedrawContent() + { + // TODO: Rebuild the whole pad control here, renew all resource strings whatever + // Note that you do not need to recreate the control. + } + + /// <summary> + /// Cleans up all used resources + /// </summary> + public override void Dispose() + { + ctl.Dispose(); + } + } + + class ServerToolTreeView : TreeView + { + public ServerToolTreeView(): base() + { + // this is the wrong place for this, but lets give it a go... + DbModelInfoService.LoadNamesFromFiles(); + Rebuild(); + + } + + /// <summary> + /// Rebuilds the database connection tree. + /// Should only be called from a delegate via Invoke or BeginInvoke. + /// </summary> + public void Rebuild() + { + this.BeginUpdate(); + // TODO: put the Rebuild... behaviour into a view builder; + TreeNode dbNode = null; + TreeNode[] dbNodes = this.Nodes.Find("DatabaseExplorer", true); + + // lets assume there is only one with this above name + if (dbNodes.Length == 0) { + LoggingService.Debug("could not find DatabaseExplorer Node, so creating it now"); + dbNode = new TreeNode(); + dbNode.Text = "Database Explorer"; + dbNode.Name = "DatabaseExplorer"; + this.Nodes.Add(dbNode); + } else { + dbNode = dbNodes[0]; + } + + // create the context menu for the database server node + ContextMenuStrip cMenu = new ContextMenuStrip(); + ToolStripMenuItem addConnectionMenuItem = + new ToolStripMenuItem("Add Connection"); + addConnectionMenuItem.Click += new EventHandler(AddDbConnectionClickHandler); + + ToolStripMenuItem deleteConnectionMenuItem = + new ToolStripMenuItem("Delete Connection"); + deleteConnectionMenuItem.Click += new EventHandler(DeleteDbConnectionClickHandler); + + ToolStripMenuItem saveMetadataMenuItem = + new ToolStripMenuItem("Save All"); + saveMetadataMenuItem.Click += new EventHandler(SaveDbModelInfoClickHandler); + + + cMenu.Items.AddRange(new ToolStripMenuItem[] + { + addConnectionMenuItem, + deleteConnectionMenuItem, + saveMetadataMenuItem + } + ); + dbNode.ContextMenuStrip = cMenu; + + // Rebuild each of the root nodes in the ServerToolTreeView + dbNode.Nodes.Clear(); + foreach (string name in DbModelInfoService.Names) { + TreeNode dbModelInfoNode = CreateDbModelInfoNode(name); + TreeNode connectionNode = CreateConnectionPropertiesNode(name); + TreeNode metadataNode = CreateMetaDataNode(name); + dbModelInfoNode.Nodes.Add(connectionNode); + dbModelInfoNode.Nodes.Add(metadataNode); + dbNode.Nodes.Add(dbModelInfoNode); + } + this.EndUpdate(); + } + + public TreeNode CreateDbModelInfoNode(string name) + { + TreeNode treeNode = new TreeNode(name); + treeNode.Tag = "ConnectionRoot"; + // create and add the menustrip for this node + + NodeAwareContextMenuStrip cMenu = new NodeAwareContextMenuStrip(treeNode); + + // create menu items + ToolStripMenuItem setConnectionStringMenuItem = + new ToolStripMenuItem("Set Connection String"); + setConnectionStringMenuItem.Click += new EventHandler(SetConnectionStringOnDbModelInfoClickHandler); + + ToolStripMenuItem loadMetadataFromConnectionMenuItem = + new ToolStripMenuItem("Load Metadata from Connection"); + loadMetadataFromConnectionMenuItem.Click += new EventHandler(LoadMetadataFromConnectionClickHandler); + + ToolStripMenuItem loadMetadataFromFileMenuItem = + new ToolStripMenuItem("Load Metadata from File"); + loadMetadataFromFileMenuItem.Click += new EventHandler(LoadMetadataFromFileClickHandler); + + + cMenu.Items.AddRange(new ToolStripMenuItem[] + { + setConnectionStringMenuItem, + loadMetadataFromConnectionMenuItem, + loadMetadataFromFileMenuItem + }); + + treeNode.ContextMenuStrip = cMenu; + return treeNode; + } + + /// <summary> + /// + /// </summary> + /// <param name="name"></param> + /// <returns>a TreeNode representation of the connection properties + /// of the connection</returns> + public TreeNode CreateConnectionPropertiesNode(string name) + { + // create sub TreeNodes for the connection string and invariant name if they exist + DbModelInfo modelInfo = DbModelInfoService.GetDbModelInfo(name); + if (name == null) throw new KeyNotFoundException(); + string connectionString = modelInfo.ConnectionString; + string invariantName = modelInfo.InvariantName; + + TreeNode attributesNode = new TreeNode("Connection Properties"); + + if (connectionString != null) { + TreeNode cstringNode = new TreeNode("Connection String: " + connectionString); + attributesNode.Nodes.Add(cstringNode); + } + + if (invariantName != null) { + TreeNode invNameNode = new TreeNode("Invariant Name: " + invariantName); + attributesNode.Nodes.Add(invNameNode); + } + + return attributesNode; + } + + public TreeNode CreateMetaDataNode(string name) + { + TreeNode metaNode = new TreeNode("Db Objects"); + metaNode.Name = name + ":MetaData"; + DbModelInfo info = DbModelInfoService.GetDbModelInfo(name); + DataTable metadataCollectionsTable = info.Tables[TableNames.MetaDataCollections]; + if (metadataCollectionsTable != null) { + for (int i = 0; i < TableNames.PrimaryObjects.Length; i++) { + string metadataCollectionName = TableNames.PrimaryObjects[i]; + LoggingService.Debug("looking for metadata: " + metadataCollectionName); + DataTable metaCollectionTable = info.Tables[metadataCollectionName]; + LoggingService.Debug("found metadata collection: " + metadataCollectionName); + TreeNode collectionNode = new TreeNode(metadataCollectionName); + collectionNode.Name = name + ":Collection:" + metadataCollectionName; + metaNode.Nodes.Add(collectionNode); + foreach (DataRow dbObjectRow in metaCollectionTable.Rows) { + // TODO: >>>>>>>NEXT: at this point it is not enough to make this assumption - it doesn't hold + // for SQLServer for example, only for Oracle. The following text illustrates the difference between + // SQLServer and Oracle for the Users metadatacollection. + + /* + * C:\workspace\ExampleDBFactories\DbExperiments\bin\Debug>DbExperiments.exe Users + +uid user_name createdate updatedate +0 public 08/04/2003 09:10:19 14/10/2005 01:36:15 +1 dbo 08/04/2003 09:10:19 08/04/2003 09:10:19 +2 guest 08/04/2003 09:10:19 08/04/2003 09:10:19 +3 INFORMATION_SCHEMA 14/10/2005 01:36:06 14/10/2005 01:36:06 +4 sys 14/10/2005 01:36:06 14/10/2005 01:36:06 +5 ##MS_AgentSigningCertificate## 26/08/2006 23:04:16 26/08/2006 23:04:16 +16384 db_owner 08/04/2003 09:10:19 14/10/2005 01:36:15 +16385 db_accessadmin 08/04/2003 09:10:19 14/10/2005 01:36:15 +16386 db_securityadmin 08/04/2003 09:10:19 14/10/2005 01:36:15 +16387 db_ddladmin 08/04/2003 09:10:19 14/10/2005 01:36:15 +16389 db_backupoperator 08/04/2003 09:10:19 14/10/2005 01:36:15 +16390 db_datareader 08/04/2003 09:10:19 14/10/2005 01:36:15 +16391 db_datawriter 08/04/2003 09:10:19 14/10/2005 01:36:15 +16392 db_denydatareader 08/04/2003 09:10:19 14/10/2005 01:36:15 +16393 db_denydatawriter 08/04/2003 09:10:19 14/10/2005 01:36:15 + +C:\workspace\ExampleDBFactories\DbExperiments\bin\Debug>DbExperiments.exe Users + +NAME ID CREATEDATE +ANONYMOUS 28 07/02/2006 22:40:15 +CTXSYS 25 07/02/2006 22:38:38 +DBSNMP 23 07/02/2006 22:35:21 +DEV 36 26/07/2006 00:09:58 +DIP 18 07/02/2006 22:17:03 +FLOWS_020100 35 07/02/2006 22:52:43 +FLOWS_FILES 34 07/02/2006 22:52:43 +HR 33 07/02/2006 22:51:21 +MDSYS 32 07/02/2006 22:44:47 +OUTLN 11 07/02/2006 22:10:24 +SYS 0 07/02/2006 22:10:13 +SYSTEM 5 07/02/2006 22:10:13 +TSMSYS 20 07/02/2006 22:27:15 +XDB 27 07/02/2006 22:40:14 + +C:\workspace\ExampleDBFactories\DbExperiments\bin\Debug> + * + * + */ + TreeNode objectNode = null; + if (dbObjectRow.ItemArray.Length > 1) { + objectNode = new TreeNode((string)dbObjectRow[1]); + objectNode.Name = name + ":Object:" + (string)dbObjectRow[1]; + } else { + objectNode = new TreeNode((string)dbObjectRow[0]); + objectNode.Name = name + ":Object:" + (string)dbObjectRow[0]; + } + // HACK All this building stuff needs to be externalise I think + if (metadataCollectionName.Equals("Tables")) { + // add the handler to invoke describer + NodeAwareContextMenuStrip cMenu = new NodeAwareContextMenuStrip(objectNode); + ToolStripMenuItem invokeDescriberMenuItem = new ToolStripMenuItem("Describe"); + invokeDescriberMenuItem.Click += new EventHandler(DescribeTableClickHandler); + cMenu.Items.Add(invokeDescriberMenuItem); + objectNode.ContextMenuStrip = cMenu; + } + + + +// TreeNode ownerNode = new TreeNode("Owner: " + (string)dbObjectRow["OWNER"]); +// TreeNode typeNode = new TreeNode("Type: " + (string)dbObjectRow["TYPE"]); +// // TODO: add fields to each Table +// TreeNode fieldsNode = new TreeNode("Fields [TODO]"); +// objectNode.Nodes.AddRange(new TreeNode[] {ownerNode, typeNode, fieldsNode }); + collectionNode.Nodes.Add(objectNode); + } + } + } + return metaNode; + } + + /// <summary> + /// Uses a dialog to get the logical name of a new Connection then + /// adds a new DbModelInfo for it to the cache and updates the DatabaseServer + /// Tree. + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + public void AddDbConnectionClickHandler(object sender, EventArgs e) + { + LoggingService.Debug("add connection clicked"); + + // get the logical name of the new connection + string logicalName = null; + using (GetConnectionLogicalNameDialog dialog = new GetConnectionLogicalNameDialog()) { + dialog.ShowDialog(); + logicalName = dialog.LogicalConnectionName; + } + if (logicalName.Equals("") || logicalName == null) return; + + LoggingService.Debug("name received is: " + logicalName); + + // add a new DbModelInfo to the cache + DbModelInfoService.Add(logicalName, null, null); + + // rebuild the database server node + this.BeginInvoke(new MethodInvoker(this.Rebuild)); + } + + public void DeleteDbConnectionClickHandler(object sender, EventArgs e) + { + LoggingService.Debug("delete connection clicked"); + } + + public void SaveDbModelInfoClickHandler(object sender, EventArgs e) + { + // save each DbModelInfo separately, confirming overwrite where necessary + LoggingService.Debug("save all metadata clicked - will iterate through each and attempt to save"); + IList<string> names = DbModelInfoService.Names; + foreach (string name in names) { + bool saved = DbModelInfoService.SaveToFile(name, false); + if (!saved) { + DialogResult result = MessageBox.Show("Overwrite existing file for connection: " + name + "?", + "File exists for connection", MessageBoxButtons.YesNo, + MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); + if (result.Equals(DialogResult.Yes)) { + DbModelInfoService.SaveToFile(name, true); + } + } + } + } + + public void LoadMetadataFromFileClickHandler(object sender, EventArgs e) + { + LoggingService.Debug("load metadata from file clicked"); + string logicalConnectionName = getConnectionName(sender); + DbModelInfoService.LoadFromFile(logicalConnectionName); + this.BeginInvoke(new MethodInvoker(this.Rebuild)); + } + + private static string getConnectionName(object sender) + { + ToolStripMenuItem menuItem = sender as ToolStripMenuItem; + NodeAwareContextMenuStrip toolStrip = menuItem.Owner as NodeAwareContextMenuStrip; + TreeNode node = toolStrip.TreeNode; + while ((node.Tag == null) || (!node.Tag.Equals("ConnectionRoot"))) { + node = node.Parent; + } + string connectionLogicalName = node.Text; + return connectionLogicalName; + } + + public void SetConnectionStringOnDbModelInfoClickHandler(object sender, EventArgs e) + { + string connectionLogicalName = getConnectionName(sender); + LoggingService.Debug("add connection string clicked for item with name: " + connectionLogicalName); + + // use the ConnectionStringDefinitionDialog to get a connection string and invariant name + ConnectionStringDefinitionDialog definitionDialog = new ConnectionStringDefinitionDialog(); + DialogResult result = definitionDialog.ShowDialog(); + + // if the dialog was cancelled then do nothing + if (result == DialogResult.Cancel) { + return; + } + + // if the dialog was submitted and connection string has changed then clear the DbModelInfo metadata + // note that is is not required for the Connection string to be valid - it may be work + // in progress and a user might want to save a partially formed connection string + + DbModelInfo dbModelInfo = DbModelInfoService.GetDbModelInfo(connectionLogicalName); + string connectionString = dbModelInfo.ConnectionString; + string newConnectionString = definitionDialog.ConnectionString; + + if (newConnectionString == null) { + return; + } + + dbModelInfo.ConnectionString = newConnectionString; + dbModelInfo.InvariantName = definitionDialog.InvariantName; + + // rebuild the database explorer node + this.BeginInvoke(new MethodInvoker(this.Rebuild)); + } + + public void LoadMetadataFromConnectionClickHandler(object sender, EventArgs args) + { + string connectionLogicalName = getConnectionName(sender); + LoggingService.Debug("load metadata from connection clicked for connection with name: " + + connectionLogicalName); + try { + DbModelInfoService.LoadMetadataFromConnection(connectionLogicalName); + } + catch(DbException e) { + MessageService.ShowError(e, + "An Exception was thrown while trying to connect to: " + connectionLogicalName); + } + } + + public void DescribeTableClickHandler(object sender, EventArgs args) + { + string logicalConnectionName = getConnectionName(sender); + ToolStripMenuItem item = sender as ToolStripMenuItem; + NodeAwareContextMenuStrip s = item.Owner as NodeAwareContextMenuStrip; + string tableName = s.TreeNode.Text; + LoggingService.Debug("describe table clicked for: " + logicalConnectionName + " and table name: " + tableName); + DataTable tableInfo = DbModelInfoService.GetTableInfo(logicalConnectionName, tableName); + //DataSet dbModelInfo = DbModelInfoService.GetDbModelInfo(logicalConnectionName); +// TableDescribeForm describeForm = new TableDescribeForm(tableInfo); +// describeForm.Show(); + TableDescribeViewContent tableDescribeViewContent = new TableDescribeViewContent(tableInfo, tableName); + WorkbenchSingleton.Workbench.ShowView(tableDescribeViewContent); + } + } + + class NodeAwareContextMenuStrip : ContextMenuStrip + { + TreeNode treeNodeAttached; + + public NodeAwareContextMenuStrip(TreeNode treeNodeAttached) : base() + { + this.treeNodeAttached = treeNodeAttached; + } + + public TreeNode TreeNode { + get { + return treeNodeAttached; + } + } + } +} + + + + +