/// <summary> /// Initializes a new instance of the BaseSession class based on the specified connection string. /// </summary> /// <param name="connectionString">The connection used to create the session.</param> /// <param name="client">A <see cref="Client"/> object.</param> /// <exception cref="ArgumentNullException"><paramref name="connectionString"/> is <c>null</c>.</exception> /// <exception cref="UriFormatException">Unable to parse the <paramref name="connectionString"/> when /// in URI format.</exception> /// <remarks> /// <para>When using Unix sockets the <c>protocol=unix</c> or <c>protocol=unixsocket</c> connection option is required. /// This will enable elements passed in the <c>server</c> connection option to be treated as Unix sockets. The user is also required /// to explicitly set <c>sslmode</c> to <c>none</c> since X Plugin does not support SSL when using Unix sockets. Note that /// <c>protocol=unix</c> and <c>protocol=unixsocket</c> are synonyms.</para> /// <para> </para> /// <para>Multiple hosts can be specified as part of the <paramref name="connectionString"/>, /// which enables client-side failover when trying to establish a connection.</para> /// <para> </para> /// <para>Connection URI examples: /// <para />- mysqlx://test:test@[192.1.10.10,localhost] /// <para />- mysqlx://test:test@[192.1.10.10,127.0.0.1] /// <para />- mysqlx://root:@[../tmp/mysqlx.sock,/tmp/mysqld.sock]?protocol=unix&sslmode=none /// <para />- mysqlx://test:test@[192.1.10.10:33060,127.0.0.1:33060] /// <para />- mysqlx://test:test@[192.1.10.10,120.0.0.2:22000,[::1]:33060]/test?connectiontimeout=10 /// <para />- mysqlx://test:test@[(address=server.example,priority=20),(address=127.0.0.1,priority=100)] /// <para />- mysqlx://test:test@[(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25)] /// </para> /// <para> </para> /// <para>Connection string examples: /// <para />- server=10.10.10.10,localhost;port=33060;uid=test;password=test; /// <para />- host=10.10.10.10,192.101.10.2,localhost;port=5202;uid=test;password=test; /// <para />- host=./tmp/mysqld.sock,/var/run/mysqldx.sock;port=5202;uid=root;protocol=unix;sslmode=none; /// <para />- server=(address=server.example,priority=20),(address=127.0.0.1,priority=100);port=33060;uid=test;password=test; /// <para />- server=(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25);port=33060;uid=test;password=test; /// </para> /// <para> </para> /// <para>Failover methods</para> /// <para>- Sequential: Connection attempts will be performed in a sequential order, that is, one after another until /// a connection is successful or all the elements from the list have been tried. /// </para> /// <para>- Priority based: If a priority is provided, the connection attemps will be performed in descending order, starting /// with the host with the highest priority. Priority must be a value between 0 and 100. Additionally, it is required to either /// give a priority for every host or no priority to any host. /// </para> /// </remarks> internal BaseSession(string connectionString, Client client = null) : this() { if (string.IsNullOrWhiteSpace(connectionString)) { throw new ArgumentNullException("connectionString"); } _client = client; this._connectionString = ParseConnectionData(connectionString, client); // Multiple hosts were specified. if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) { _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); Settings.ConnectionString = this._connectionString; Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); } // A single host was specified. else { Settings.ConnectionString = _connectionString; if (!(_connectionString.Contains("sslmode") || _connectionString.Contains("ssl mode") || _connectionString.Contains("ssl-mode"))) { Settings.SslMode = MySqlSslMode.Required; } Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); if (Settings.DnsSrv) { var dnsSrvRecords = DnsResolver.GetDnsSrvRecords(Settings.Server); FailoverManager.SetHostList(dnsSrvRecords.ConvertAll(r => new FailoverServer(r.Target, r.Port, r.Priority)), FailoverMethod.Sequential); _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); Settings.ConnectionString = this._connectionString; } else { _internalSession = InternalSession.GetSession(Settings); } } // Set the default schema if provided by the user. if (!string.IsNullOrWhiteSpace(Settings.Database)) { DefaultSchema = GetSchema(Settings.Database); } }
/// <summary> /// Initializes a new instance of the BaseSession class based on the specified anonymous type object. /// </summary> /// <param name="connectionData">The connection data as an anonymous type used to create the session.</param> /// <param name="client">A <see cref="Client"/> object.</param> /// <exception cref="ArgumentNullException"><paramref name="connectionData"/> is null.</exception> /// <remarks> /// <para>Multiple hosts can be specified as part of the <paramref name="connectionData"/>, which enables client-side failover when trying to /// establish a connection.</para> /// <para> </para> /// <para>To assign multiple hosts, create a property similar to the connection string examples shown in /// <see cref="BaseSession(string)"/>. Note that the value of the property must be a string. /// </para> /// </remarks> internal BaseSession(object connectionData, Client client = null) : this() { if (connectionData == null) { throw new ArgumentNullException("connectionData"); } _client = client; if (client == null) { FailoverManager.Reset(); } var values = Tools.GetDictionaryFromAnonymous(connectionData); if (!values.Keys.Any(s => s.ToLowerInvariant() == PORT_CONNECTION_OPTION_KEYWORD)) { values.Add(PORT_CONNECTION_OPTION_KEYWORD, X_PROTOCOL_DEFAULT_PORT); } bool hostsParsed = false; foreach (var value in values) { if (!Settings.ContainsKey(value.Key)) { throw new KeyNotFoundException(string.Format(ResourcesX.InvalidConnectionStringAttribute, value.Key)); } Settings.SetValue(value.Key, value.Value); if (!hostsParsed && !string.IsNullOrEmpty(Settings[SERVER_CONNECTION_OPTION_KEYWORD].ToString())) { var server = value.Value.ToString(); if (IsUnixSocket(server)) { Settings.SetValue(value.Key, server = NormalizeUnixSocket(server)); } FailoverManager.ParseHostList(server, true, false); if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) { Settings[SERVER_CONNECTION_OPTION_KEYWORD] = null; } else if (FailoverManager.FailoverGroup != null) { Settings[SERVER_CONNECTION_OPTION_KEYWORD] = FailoverManager.FailoverGroup.Hosts[0].Host; } hostsParsed = true; } } this._connectionString = Settings.ToString(); Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) { // Multiple hosts were specified. _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); Settings.ConnectionString = _connectionString; } else { if (Settings.DnsSrv) { var dnsSrvRecords = DnsResolver.GetDnsSrvRecords(Settings.Server); FailoverManager.SetHostList(dnsSrvRecords.ConvertAll(r => new FailoverServer(r.Target, r.Port, null)), FailoverMethod.Sequential); _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); Settings.ConnectionString = this._connectionString; } else { _internalSession = InternalSession.GetSession(Settings); } } if (!string.IsNullOrWhiteSpace(Settings.Database)) { DefaultSchema = GetSchema(Settings.Database); } }