You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
578 lines
25 KiB
578 lines
25 KiB
// Copyright (c) 2018, 2021, Oracle and/or its affiliates.
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License, version 2.0, as
|
|
// published by the Free Software Foundation.
|
|
//
|
|
// This program is also distributed with certain software (including
|
|
// but not limited to OpenSSL) that is licensed under separate terms,
|
|
// as designated in a particular file or component or in included license
|
|
// documentation. The authors of MySQL hereby grant you an
|
|
// additional permission to link the program and your derivative works
|
|
// with the separately licensed software that they have included with
|
|
// MySQL.
|
|
//
|
|
// Without limiting anything contained in the foregoing, this file,
|
|
// which is part of MySQL Connector/NET, is also subject to the
|
|
// Universal FOSS Exception, version 1.0, a copy of which can be found at
|
|
// http://oss.oracle.com/licenses/universal-foss-exception.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License, version 2.0, for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software Foundation, Inc.,
|
|
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
using MySql.Data.common;
|
|
using MySql.Data.Common;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data.Common;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Security.Authentication;
|
|
using System.Text;
|
|
using Sog.Properties;
|
|
|
|
using static MySql.Data.common.MySqlConnectionStringOption;
|
|
|
|
namespace MySql.Data.MySqlClient
|
|
{
|
|
/// <summary>
|
|
/// Abstract class that provides common functionality for connection options that apply for all protocols.
|
|
/// </summary>
|
|
public abstract class MySqlBaseConnectionStringBuilder : DbConnectionStringBuilder
|
|
{
|
|
/// <summary>
|
|
/// Readonly field containing a collection of protocol shared connection options.
|
|
/// </summary>
|
|
internal static readonly MySqlConnectionStringOptionCollection Options = new MySqlConnectionStringOptionCollection();
|
|
|
|
static MySqlBaseConnectionStringBuilder()
|
|
{
|
|
// Server options.
|
|
Options.Add(new MySqlConnectionStringOption("server", "host,data source,datasource", typeof(string), "" /*"localhost"*/, false));
|
|
Options.Add(new MySqlConnectionStringOption("database", "initial catalog", typeof(string), string.Empty, false));
|
|
Options.Add(new MySqlConnectionStringOption("protocol", "connection protocol,connectionprotocol", typeof(MySqlConnectionProtocol), MySqlConnectionProtocol.Sockets, false,
|
|
(SetterDelegate)((msb, sender, value) =>
|
|
{
|
|
#if !NETFRAMEWORK
|
|
MySqlConnectionProtocol enumValue;
|
|
if (Enum.TryParse<MySqlConnectionProtocol>(value.ToString(), true, out enumValue))
|
|
{
|
|
if (!Platform.IsWindows() && (enumValue == MySqlConnectionProtocol.Memory || enumValue == MySqlConnectionProtocol.Pipe))
|
|
{
|
|
throw new PlatformNotSupportedException(string.Format(Resources.OptionNotCurrentlySupported, $"Protocol={value}"));
|
|
}
|
|
}
|
|
#endif
|
|
msb.SetValue("protocol", value);
|
|
}),
|
|
(GetterDelegate)((msb, sender) => msb.ConnectionProtocol)));
|
|
Options.Add(new MySqlConnectionStringOption("port", null, typeof(uint), (uint)3306, false));
|
|
Options.Add(new MySqlConnectionStringOption("dns-srv", "dnssrv", typeof(bool), false, false));
|
|
|
|
// Authentication options.
|
|
Options.Add(new MySqlConnectionStringOption("user id", "uid,username,user name,user,userid", typeof(string), "", false));
|
|
Options.Add(new MySqlConnectionStringOption("password", "pwd", typeof(string), "", false));
|
|
Options.Add(new MySqlConnectionStringOption("certificatefile", "certificate file", typeof(string), null, false));
|
|
Options.Add(new MySqlConnectionStringOption("certificatepassword", "certificate password,ssl-ca-pwd", typeof(string), null, false));
|
|
Options.Add(new MySqlConnectionStringOption("certificatestorelocation", "certificate store location", typeof(MySqlCertificateStoreLocation), MySqlCertificateStoreLocation.None, false));
|
|
Options.Add(new MySqlConnectionStringOption("certificatethumbprint", "certificate thumb print", typeof(string), null, false));
|
|
Options.Add(new MySqlConnectionStringOption("sslmode", "ssl mode,ssl-mode", typeof(MySqlSslMode), MySqlSslMode.Preferred, false,
|
|
(SetterDelegate)((msb, sender, value) =>
|
|
{
|
|
MySqlSslMode newValue = (MySqlSslMode)Enum.Parse(typeof(MySqlSslMode), value.ToString(), true);
|
|
if (newValue == MySqlSslMode.None && msb.TlsVersion != null)
|
|
{
|
|
throw new ArgumentException(Resources.InvalidTlsVersionAndSslModeOption, nameof(TlsVersion));
|
|
}
|
|
|
|
msb.SetValue("sslmode", newValue);
|
|
}),
|
|
(GetterDelegate)((msb, sender) => { return msb.SslMode; })));
|
|
Options.Add(new MySqlConnectionStringOption("sslca", "ssl-ca", typeof(string), null, false,
|
|
(SetterDelegate)((msb, sender, value) => { msb.SslCa = value as string; }),
|
|
(GetterDelegate)((msb, sender) => { return msb.SslCa; })));
|
|
Options.Add(new MySqlConnectionStringOption("sslkey", "ssl-key", typeof(string), null, false));
|
|
Options.Add(new MySqlConnectionStringOption("sslcert", "ssl-cert", typeof(string), null, false));
|
|
Options.Add(new MySqlConnectionStringOption("tlsversion", "tls-version,tls version", typeof(string), null, false,
|
|
(SetterDelegate)((msb, sender, value) =>
|
|
{
|
|
if (value == null || string.IsNullOrWhiteSpace((string)value))
|
|
{
|
|
msb.SetValue("tlsversion", null);
|
|
return;
|
|
}
|
|
|
|
if (msb.SslMode == MySqlSslMode.None)
|
|
{
|
|
throw new ArgumentException(Resources.InvalidTlsVersionAndSslModeOption, nameof(TlsVersion));
|
|
}
|
|
|
|
string strValue = ((string)value).TrimStart('[', '(').TrimEnd(']', ')').Replace(" ", string.Empty);
|
|
if (string.IsNullOrWhiteSpace(strValue) || strValue == ",")
|
|
{
|
|
throw new ArgumentException(Resources.TlsVersionNotSupported);
|
|
}
|
|
|
|
SslProtocols protocols = SslProtocols.None;
|
|
foreach (string opt in strValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
|
{
|
|
string tls = opt.ToLowerInvariant().Replace("v", "").Replace(".", "");
|
|
if (tls.Equals("tls1") || tls.Equals("tls10"))
|
|
{
|
|
tls = "tls";
|
|
}
|
|
|
|
SslProtocols protocol;
|
|
if (!tls.StartsWith("tls", StringComparison.OrdinalIgnoreCase)
|
|
|| (!Enum.TryParse<SslProtocols>(tls, true, out protocol) && !tls.Equals("tls13", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
string info = string.Empty;
|
|
#if NET48 || NETSTANDARD2_1
|
|
info = ", TLSv1.3";
|
|
#endif
|
|
throw new ArgumentException(string.Format(Resources.InvalidTlsVersionOption, opt, info), nameof(TlsVersion));
|
|
}
|
|
|
|
protocols |= protocol;
|
|
}
|
|
|
|
string strProtocols = protocols == SslProtocols.None ? string.Empty : Enum.Format(typeof(SslProtocols), protocols, "G");
|
|
strProtocols = (value.ToString().Equals("Tls13", StringComparison.OrdinalIgnoreCase)
|
|
|| value.ToString().Equals("Tlsv1.3", StringComparison.OrdinalIgnoreCase)) ? "Tls13" : strProtocols;
|
|
msb.SetValue("tlsversion", strProtocols);
|
|
}),
|
|
(GetterDelegate)((msb, sender) => { return msb.TlsVersion; })));
|
|
|
|
// Other properties.
|
|
Options.Add(new MySqlConnectionStringOption("keepalive", "keep alive", typeof(uint), (uint)0, false));
|
|
|
|
// Language and charset options.
|
|
Options.Add(new MySqlConnectionStringOption("characterset", "character set,charset", typeof(string), "", false));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a flag indicating if the object has access to procedures.
|
|
/// </summary>
|
|
internal bool HasProcAccess { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a dictionary representing key-value pairs for each connection option.
|
|
/// </summary>
|
|
internal Dictionary<string, object> values { get; set; }
|
|
#region Server Properties
|
|
|
|
/// <summary>
|
|
/// Gets or sets the name of the server.
|
|
/// </summary>
|
|
/// <value>The server.</value>
|
|
[Category("Connection")]
|
|
[Description("Server to connect to")]
|
|
[RefreshProperties(RefreshProperties.All)]
|
|
public string Server
|
|
{
|
|
get { return this["server"] as string; }
|
|
set { this.SetValue("server", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the name of the database for the initial connection.
|
|
/// </summary>
|
|
[Category("Connection")]
|
|
[Description("Database to use initially")]
|
|
[RefreshProperties(RefreshProperties.All)]
|
|
public string Database
|
|
{
|
|
get { return this.values["database"] as string; }
|
|
set { this.SetValue("database", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the protocol that should be used for communicating
|
|
/// with MySQL.
|
|
/// </summary>
|
|
[Category("Connection")]
|
|
[DisplayName("Connection Protocol")]
|
|
[Description("Protocol to use for connection to MySQL")]
|
|
[RefreshProperties(RefreshProperties.All)]
|
|
public MySqlConnectionProtocol ConnectionProtocol
|
|
{
|
|
get { return (MySqlConnectionProtocol)this.values["protocol"]; }
|
|
set { this.SetValue("protocol", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the port number that is used when the socket
|
|
/// protocol is being used.
|
|
/// </summary>
|
|
[Category("Connection")]
|
|
[Description("Port to use for TCP/IP connections")]
|
|
[RefreshProperties(RefreshProperties.All)]
|
|
public uint Port
|
|
{
|
|
get { return (uint)this.values["port"]; }
|
|
set { this.SetValue("port", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a boolean value that indicates whether this connection
|
|
/// should resolve DNS SRV records.
|
|
/// </summary>
|
|
[Category("Connection")]
|
|
[DisplayName("DNS SRV")]
|
|
[Description("The connection should resolve DNS SRV records.")]
|
|
[RefreshProperties(RefreshProperties.All)]
|
|
public bool DnsSrv
|
|
{
|
|
get { return (bool)this.values["dns-srv"]; }
|
|
set { this.SetValue("dns-srv", value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Authentication Properties
|
|
|
|
/// <summary>
|
|
/// Gets or sets the user ID that should be used to connect with.
|
|
/// </summary>
|
|
[Category("Security")]
|
|
[DisplayName("User ID")]
|
|
[Description("Indicates the user ID to be used when connecting to the data source.")]
|
|
[RefreshProperties(RefreshProperties.All)]
|
|
public string UserID
|
|
{
|
|
get { return (string)this.values["user id"]; }
|
|
set { this.SetValue("user id", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the password that should be used to make a connection.
|
|
/// </summary>
|
|
[Category("Security")]
|
|
[Description("Indicates the password to be used when connecting to the data source.")]
|
|
[RefreshProperties(RefreshProperties.All)]
|
|
[PasswordPropertyText(true)]
|
|
public string Password
|
|
{
|
|
get { return (string)this.values["password"]; }
|
|
set { this.SetValue("password", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the path to the certificate file to be used.
|
|
/// </summary>
|
|
[Category("Authentication")]
|
|
[DisplayName("Certificate File")]
|
|
[Description("Certificate file in PKCS#12 format (.pfx) or path to a local file that " +
|
|
"contains a list of trusted TLS/SSL CAs (.pem).")]
|
|
public string CertificateFile
|
|
{
|
|
get { return (string)this.values["certificatefile"]; }
|
|
set { this.SetValue("certificatefile", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the password to be used in conjunction with the certificate file.
|
|
/// </summary>
|
|
[Category("Authentication")]
|
|
[DisplayName("Certificate Password")]
|
|
[Description("Password for certificate file")]
|
|
public string CertificatePassword
|
|
{
|
|
get { return (string)this.values["certificatepassword"]; }
|
|
set { this.SetValue("certificatepassword", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the location to a personal store where a certificate is held.
|
|
/// </summary>
|
|
[Category("Authentication")]
|
|
[DisplayName("Certificate Store Location")]
|
|
[Description("Certificate Store Location for client certificates")]
|
|
[DefaultValue(MySqlCertificateStoreLocation.None)]
|
|
public MySqlCertificateStoreLocation CertificateStoreLocation
|
|
{
|
|
get { return (MySqlCertificateStoreLocation)this.values["certificatestorelocation"]; }
|
|
set { this.SetValue("certificatestorelocation", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a certificate thumbprint to ensure correct identification of a certificate contained within a personal store.
|
|
/// </summary>
|
|
[Category("Authentication")]
|
|
[DisplayName("Certificate Thumbprint")]
|
|
[Description("Certificate thumbprint. Can be used together with Certificate " +
|
|
"Store Location parameter to uniquely identify the certificate to be used " +
|
|
"for SSL authentication.")]
|
|
public string CertificateThumbprint
|
|
{
|
|
get { return (string)this.values["certificatethumbprint"]; }
|
|
set { this.SetValue("certificatethumbprint", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether to use SSL connections and how to handle server certificate errors.
|
|
/// </summary>
|
|
[DisplayName("Ssl Mode")]
|
|
[Category("Authentication")]
|
|
[Description("SSL properties for connection.")]
|
|
[DefaultValue(MySqlSslMode.None)]
|
|
public MySqlSslMode SslMode
|
|
{
|
|
get { return (MySqlSslMode)this.values["sslmode"]; }
|
|
set { this.SetValue("sslmode", value); }
|
|
}
|
|
|
|
[DisplayName("Ssl Ca")]
|
|
[Category("Authentication")]
|
|
[Description("Path to a local file that contains a list of trusted TLS/SSL CAs.")]
|
|
public string SslCa
|
|
{
|
|
get { return this.CertificateFile; }
|
|
set
|
|
{
|
|
this.CertificateFile = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the TLS versions to use in a <see cref="SslMode">SSL connection</see> to the server.
|
|
/// </summary>
|
|
/// <example>
|
|
/// Tls version=TLSv1.1,TLSv1.2;
|
|
/// </example>
|
|
[DisplayName("TLS version")]
|
|
[Category("Security")]
|
|
[Description("TLS versions to use in a SSL connection to the server.")]
|
|
public string TlsVersion
|
|
{
|
|
get { return (string)this.values["tlsversion"]; }
|
|
set { this.SetValue("tlsversion", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the path to a local key file in PEM format to use for establishing an encrypted connection.
|
|
/// </summary>
|
|
[DisplayName("Ssl Key")]
|
|
[Category("Authentication")]
|
|
[Description("Name of the SSL key file in PEM format to use for establishing an encrypted connection.")]
|
|
public string SslKey
|
|
{
|
|
get { return (string)this.values["sslkey"]; }
|
|
set { this.SetValue("sslkey", value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the path to a local certificate file in PEM format to use for establishing an encrypted connection.
|
|
/// </summary>
|
|
[DisplayName("Ssl Cert")]
|
|
[Category("Authentication")]
|
|
[Description("Name of the SSL certificate file in PEM format to use for establishing an encrypted connection.")]
|
|
public string SslCert
|
|
{
|
|
get { return (string)this.values["sslcert"]; }
|
|
set { this.SetValue("sslcert", value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Other Properties
|
|
|
|
/// <summary>
|
|
/// Gets or sets the idle connection time(seconds) for TCP connections.
|
|
/// </summary>
|
|
[DisplayName("Keep Alive")]
|
|
[Description("For TCP connections, the idle connection time (in seconds) before the first keepalive packet is sent." +
|
|
"A value of 0 indicates that keepalive is not used.")]
|
|
[DefaultValue(0)]
|
|
public uint Keepalive
|
|
{
|
|
get { return (uint)this.values["keepalive"]; }
|
|
set { this.SetValue("keepalive", value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Language and Character Set Properties
|
|
|
|
/// <summary>
|
|
/// Gets or sets the character set that should be used for sending queries to the server.
|
|
/// </summary>
|
|
[DisplayName("Character Set")]
|
|
[Category("Advanced")]
|
|
[Description("Character set this connection should use.")]
|
|
[RefreshProperties(RefreshProperties.All)]
|
|
[DefaultValue("")]
|
|
public string CharacterSet
|
|
{
|
|
get { return (string)this.values["characterset"]; }
|
|
set { this.SetValue("characterset", value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Analyzes the connection string for potential duplicated or invalid connection options.
|
|
/// </summary>
|
|
/// <param name="connectionString">Connection string.</param>
|
|
/// <param name="isXProtocol">Flag that indicates if the connection is using X Protocol.</param>
|
|
/// <param name="isDefaultPort">Flag that indicates if the default port is used.</param>
|
|
internal void AnalyzeConnectionString(string connectionString, bool isXProtocol, bool isDefaultPort = true)
|
|
{
|
|
string[] queries = connectionString.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
|
var usedSslOptions = new List<string>();
|
|
bool sslModeIsNone = false;
|
|
bool isDnsSrv = false;
|
|
|
|
if (queries.FirstOrDefault(q => q.ToLowerInvariant().Contains("dns-srv=true")) != null
|
|
|| queries.FirstOrDefault(q => q.ToLowerInvariant().Contains("dnssrv=true")) != null)
|
|
{
|
|
isDnsSrv = true;
|
|
}
|
|
|
|
foreach (string query in queries)
|
|
{
|
|
string[] keyValue = query.Split('=');
|
|
if (keyValue.Length % 2 != 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var keyword = keyValue[0].ToLowerInvariant().Trim();
|
|
var value = query.Contains(",") ? query.Replace(keyword, "") : keyValue[1].ToLowerInvariant();
|
|
MySqlConnectionStringOption option = Options.Options.Where(o => o.Keyword == keyword || (o.Synonyms != null && o.Synonyms.Contains(keyword))).FirstOrDefault();
|
|
|
|
// DNS SRV option can't be used if Port, Unix Socket or Multihost are specified
|
|
if (isDnsSrv)
|
|
{
|
|
if (option.Keyword == "port" && !isDefaultPort)
|
|
{
|
|
throw new ArgumentException(Resources.DnsSrvInvalidConnOptionPort);
|
|
}
|
|
|
|
if (option.Keyword == "server" && ((value.Contains("address") && value.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Length > 2) || value.Contains(",")))
|
|
{
|
|
throw new ArgumentException(Resources.DnsSrvInvalidConnOptionMultihost);
|
|
}
|
|
|
|
if (option.Keyword == "protocol" && (value.ToLowerInvariant().Contains("unix") || value.ToLowerInvariant().Contains("unixsocket")))
|
|
{
|
|
throw new ArgumentException(Resources.DnsSrvInvalidConnOptionUnixSocket);
|
|
}
|
|
}
|
|
|
|
if (option == null
|
|
|| (option.Keyword != "sslmode"
|
|
&& option.Keyword != "certificatefile"
|
|
&& option.Keyword != "certificatepassword"
|
|
&& option.Keyword != "sslcrl"
|
|
&& option.Keyword != "sslca"
|
|
&& option.Keyword != "sslcert"
|
|
&& option.Keyword != "sslkey"
|
|
&& option.Keyword != "server"
|
|
&& option.Keyword != "tlsversion"
|
|
&& option.Keyword != "dns-srv"))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// SSL connection options can't be duplicated.
|
|
if (usedSslOptions.Contains(option.Keyword) && option.Keyword != "server" &&
|
|
option.Keyword != "tlsversion" && option.Keyword != "dns-srv")
|
|
{
|
|
throw new ArgumentException(string.Format(Resources.DuplicatedSslConnectionOption, keyword));
|
|
}
|
|
else if (usedSslOptions.Contains(option.Keyword))
|
|
{
|
|
throw new ArgumentException(string.Format(Resources.DuplicatedConnectionOption, keyword));
|
|
}
|
|
|
|
// SSL connection options can't be used if sslmode=None.
|
|
if (option.Keyword == "sslmode" && (value == "none" || value == "disabled"))
|
|
{
|
|
sslModeIsNone = true;
|
|
}
|
|
|
|
if (sslModeIsNone &&
|
|
(option.Keyword == "certificatefile"
|
|
|| option.Keyword == "certificatepassword"
|
|
|| option.Keyword == "sslcrl"
|
|
|| option.Keyword == "sslca"
|
|
|| option.Keyword == "sslcert"
|
|
|| option.Keyword == "sslkey"))
|
|
{
|
|
throw new ArgumentException(Resources.InvalidOptionWhenSslDisabled);
|
|
}
|
|
|
|
// Preferred is not allowed for the X Protocol.
|
|
if (isXProtocol && option.Keyword == "sslmode" && (value == "preferred" || value == "prefered"))
|
|
{
|
|
throw new ArgumentException(string.Format(Resources.InvalidSslMode, keyValue[1]));
|
|
}
|
|
|
|
if (option.Keyword == "sslca" || option.Keyword == "certificatefile")
|
|
{
|
|
usedSslOptions.Add("sslca");
|
|
usedSslOptions.Add("certificatefile");
|
|
}
|
|
else
|
|
{
|
|
usedSslOptions.Add(option.Keyword);
|
|
}
|
|
}
|
|
}
|
|
|
|
public string GetConnectionString(bool includePass)
|
|
{
|
|
if (includePass)
|
|
{
|
|
return this.ConnectionString;
|
|
}
|
|
|
|
var conn = new StringBuilder();
|
|
string delimiter = "";
|
|
foreach (string key in this.Keys)
|
|
{
|
|
if (string.Compare(key, "password", StringComparison.OrdinalIgnoreCase) == 0 ||
|
|
string.Compare(key, "pwd", StringComparison.OrdinalIgnoreCase) == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
conn.AppendFormat(CultureInfo.CurrentCulture, "{0}{1}={2}",
|
|
delimiter, key, this[key]);
|
|
delimiter = ";";
|
|
}
|
|
|
|
return conn.ToString();
|
|
}
|
|
|
|
internal abstract MySqlConnectionStringOption GetOption(string key);
|
|
public override int GetHashCode()
|
|
{
|
|
return base.GetHashCode();
|
|
}
|
|
|
|
internal void SetValue(string keyword, object value, [CallerMemberName] string callerName = "")
|
|
{
|
|
MySqlConnectionStringOption option = this.GetOption(keyword);
|
|
if (callerName != ".cctor" && option.IsCustomized)
|
|
{
|
|
this[keyword] = value;
|
|
}
|
|
else
|
|
{
|
|
this.SetInternalValue(keyword, value);
|
|
}
|
|
}
|
|
|
|
internal abstract void SetInternalValue(string keyword, object value);
|
|
}
|
|
}
|