public MultiShardConnection(IEnumerable <Shard> shards, string connectionString)
        {
            if (connectionString == null)
            {
                throw new ArgumentNullException("connectionString");
            }

            SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(connectionString);

            ValidateConnectionArguments(shards, connectionStringBuilder);

            // Enhance the ApplicationName with this library's name as a suffix
            string applicationName = ApplicationNameHelper.AddApplicationNameSuffix(
                connectionStringBuilder.ApplicationName,
                ApplicationNameSuffix);

            this.Shards           = shards;
            this.ShardConnections = shards.Select(
                s =>
                new Tuple <ShardLocation, DbConnection>
                (
                    s.Location,
                    new SqlConnection(
                        new SqlConnectionStringBuilder(connectionStringBuilder.ConnectionString)
            {
                ApplicationName = applicationName,
                DataSource      = s.Location.DataSource,
                InitialCatalog  = s.Location.Database
            }.ConnectionString)
                ))
                                    .ToList();
        }
        /// <summary>
        /// Ensures that the provided connection string is valid and builds the connection string
        /// to be used for DDR connection to the given shard provider.
        /// </summary>
        /// <param name="shardProvider">Shard provider containing shard to be connected to.</param>
        /// <param name="connectionString">Input connection string.</param>
        /// <returns>Connection string for DDR connection.</returns>
        private string ValidateAndPrepareConnectionString(IShardProvider shardProvider, string connectionString)
        {
            Debug.Assert(shardProvider != null);
            Debug.Assert(connectionString != null);

            // Devnote: If connection string specifies Active Directory authentication and runtime is not
            // .NET 4.6 or higher, then below call will throw.
            SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(connectionString);

            // DataSource must not be set.
            if (!string.IsNullOrEmpty(connectionStringBuilder.DataSource))
            {
                throw new ArgumentException(
                          StringUtils.FormatInvariant(
                              Errors._ShardMap_OpenConnection_ConnectionStringPropertyDisallowed,
                              "DataSource"),
                          "connectionString");
            }

            // InitialCatalog must not be set.
            if (!string.IsNullOrEmpty(connectionStringBuilder.InitialCatalog))
            {
                throw new ArgumentException(
                          StringUtils.FormatInvariant(
                              Errors._ShardMap_OpenConnection_ConnectionStringPropertyDisallowed,
                              "Initial Catalog"),
                          "connectionString");
            }

            // ConnectRetryCount must not be set (default value is 1)
            if (ShardMapUtils.IsConnectionResiliencySupported && (int)connectionStringBuilder[ShardMapUtils.ConnectRetryCount] > 1)
            {
                throw new ArgumentException(
                          StringUtils.FormatInvariant(
                              Errors._ShardMap_OpenConnection_ConnectionStringPropertyDisallowed,
                              ShardMapUtils.ConnectRetryCount),
                          "connectionString");
            }

            // Verify that either UserID/Password or provided or integrated authentication is enabled.
            SqlShardMapManagerCredentials.EnsureCredentials(connectionStringBuilder, "connectionString");

            Shard s = shardProvider.ShardInfo;

            connectionStringBuilder.DataSource     = s.Location.DataSource;
            connectionStringBuilder.InitialCatalog = s.Location.Database;

            // Append the proper post-fix for ApplicationName
            connectionStringBuilder.ApplicationName = ApplicationNameHelper.AddApplicationNameSuffix(
                connectionStringBuilder.ApplicationName,
                this.ApplicationNameSuffix);

            // Disable connection resiliency if necessary
            if (ShardMapUtils.IsConnectionResiliencySupported)
            {
                connectionStringBuilder[ShardMapUtils.ConnectRetryCount] = 0;
            }

            return(connectionStringBuilder.ConnectionString);
        }
        /// <summary>
        /// Instantiates the object that holds the credentials for accessing SQL Servers
        /// containing the shard map manager data.
        /// </summary>
        /// <param name="connectionString">
        /// Connection string for shard map manager data source.
        /// </param>
        /// <param name="secureCredential">
        ///  Secure credential for shard map manager data source.
        /// </param>
        public SqlShardMapManagerCredentials(string connectionString, SqlCredential secureCredential)
        {
            ExceptionUtils.DisallowNullArgument(connectionString, "connectionString");

            this._secureCredential = secureCredential;

            // Devnote: If connection string specifies Active Directory authentication and runtime is not
            // .NET 4.6 or higher, then below call will throw.
            SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(connectionString);

            #region GSM Validation

            // DataSource must be set.
            if (string.IsNullOrEmpty(connectionStringBuilder.DataSource))
            {
                throw new ArgumentException(
                          StringUtils.FormatInvariant(
                              Errors._SqlShardMapManagerCredentials_ConnectionStringPropertyRequired,
                              "DataSource"),
                          "connectionString");
            }

            // InitialCatalog must be set.
            if (string.IsNullOrEmpty(connectionStringBuilder.InitialCatalog))
            {
                throw new ArgumentException(
                          StringUtils.FormatInvariant(
                              Errors._SqlShardMapManagerCredentials_ConnectionStringPropertyRequired,
                              "Initial Catalog"),
                          "connectionString");
            }

            // Ensure credentials are specified for GSM connectivity.
            SqlShardMapManagerCredentials.EnsureCredentials(
                connectionStringBuilder,
                "connectionString",
                this._secureCredential);

            #endregion GSM Validation

            // Copy the input connection strings.
            _connectionStringShardMapManager = new SqlConnectionStringBuilder(connectionStringBuilder.ConnectionString);

            _connectionStringShardMapManager.ApplicationName = ApplicationNameHelper.AddApplicationNameSuffix(
                _connectionStringShardMapManager.ApplicationName,
                GlobalConstants.ShardMapManagerInternalConnectionSuffixGlobal);

            _connectionStringShard = new SqlConnectionStringBuilder(connectionStringBuilder.ConnectionString);

            _connectionStringShard.Remove("Data Source");
            _connectionStringShard.Remove("Initial Catalog");

            _connectionStringShard.ApplicationName = ApplicationNameHelper.AddApplicationNameSuffix(
                _connectionStringShard.ApplicationName,
                GlobalConstants.ShardMapManagerInternalConnectionSuffixLocal);
        }
Exemple #4
0
 // constructors
 /// <summary>
 /// Initializes a new instance of the <see cref="ConnectionSettings" /> class.
 /// </summary>
 /// <param name="authenticators">The authenticators.</param>
 /// <param name="maxIdleTime">The maximum idle time.</param>
 /// <param name="maxLifeTime">The maximum life time.</param>
 /// <param name="applicationName">The application name.</param>
 public ConnectionSettings(
     Optional <IEnumerable <IAuthenticator> > authenticators = default(Optional <IEnumerable <IAuthenticator> >),
     Optional <TimeSpan> maxIdleTime   = default(Optional <TimeSpan>),
     Optional <TimeSpan> maxLifeTime   = default(Optional <TimeSpan>),
     Optional <string> applicationName = default(Optional <string>))
 {
     _authenticators  = Ensure.IsNotNull(authenticators.WithDefault(__noAuthenticators), "authenticators").ToList();
     _maxIdleTime     = Ensure.IsGreaterThanZero(maxIdleTime.WithDefault(TimeSpan.FromMinutes(10)), "maxIdleTime");
     _maxLifeTime     = Ensure.IsGreaterThanZero(maxLifeTime.WithDefault(TimeSpan.FromMinutes(30)), "maxLifeTime");
     _applicationName = ApplicationNameHelper.EnsureApplicationNameIsValid(applicationName.WithDefault(null), nameof(applicationName));
 }
 // constructors
 /// <summary>
 /// Initializes a new instance of the <see cref="ConnectionSettings" /> class.
 /// </summary>
 /// <param name="authenticatorFactories">The authenticator factories.</param>
 /// <param name="compressors">The compressors.</param>
 /// <param name="maxIdleTime">The maximum idle time.</param>
 /// <param name="maxLifeTime">The maximum life time.</param>
 /// <param name="applicationName">The application name.</param>
 public ConnectionSettings(
     Optional <IEnumerable <IAuthenticatorFactory> > authenticatorFactories = default,
     Optional <IEnumerable <CompressorConfiguration> > compressors          = default(Optional <IEnumerable <CompressorConfiguration> >),
     Optional <TimeSpan> maxIdleTime   = default(Optional <TimeSpan>),
     Optional <TimeSpan> maxLifeTime   = default(Optional <TimeSpan>),
     Optional <string> applicationName = default(Optional <string>))
 {
     _authenticatorFactories = Ensure.IsNotNull(authenticatorFactories.WithDefault(Enumerable.Empty <IAuthenticatorFactory>()), nameof(authenticatorFactories)).ToList().AsReadOnly();
     _compressors            = Ensure.IsNotNull(compressors.WithDefault(Enumerable.Empty <CompressorConfiguration>()), nameof(compressors)).ToList();
     _maxIdleTime            = Ensure.IsGreaterThanZero(maxIdleTime.WithDefault(TimeSpan.FromMinutes(10)), "maxIdleTime");
     _maxLifeTime            = Ensure.IsGreaterThanZero(maxLifeTime.WithDefault(TimeSpan.FromMinutes(30)), "maxLifeTime");
     _applicationName        = ApplicationNameHelper.EnsureApplicationNameIsValid(applicationName.WithDefault(null), nameof(applicationName));
 }
Exemple #6
0
        private void ParseOption(string name, string value)
        {
            switch (name.ToLowerInvariant())
            {
            case "appname":
                string invalidApplicationNameMessage;
                if (!ApplicationNameHelper.IsApplicationNameValid(value, out invalidApplicationNameMessage))
                {
                    throw new MongoConfigurationException(invalidApplicationNameMessage);
                }
                _applicationName = value;
                break;

            case "authmechanism":
                _authMechanism = value;
                break;

            case "authmechanismproperties":
                foreach (var property in GetAuthMechanismProperties(name, value))
                {
                    _authMechanismProperties.Add(property.Key, property.Value);
                }
                break;

            case "authsource":
                _authSource = value;
                break;

            case "connect":
                _connect = ParseClusterConnectionMode(name, value);
                break;

            case "connecttimeout":
            case "connecttimeoutms":
                _connectTimeout = ParseTimeSpan(name, value);
                break;

            case "fsync":
                _fsync = ParseBoolean(name, value);
                break;

            case "gssapiservicename":
                _authMechanismProperties.Add("SERVICE_NAME", value);
                break;

            case "heartbeatfrequency":
            case "heartbeatfrequencyms":
            case "heartbeatinterval":
            case "heartbeatintervalms":
                _heartbeatInterval = ParseTimeSpan(name, value);
                break;

            case "heartbeattimeout":
            case "heartbeattimeoutms":
                _heartbeatTimeout = ParseTimeSpan(name, value);
                break;

            case "ipv6":
                _ipv6 = ParseBoolean(name, value);
                break;

            case "j":
            case "journal":
                _journal = ParseBoolean(name, value);
                break;

            case "maxidletime":
            case "maxidletimems":
                _maxIdleTime = ParseTimeSpan(name, value);
                break;

            case "maxlifetime":
            case "maxlifetimems":
                _maxLifeTime = ParseTimeSpan(name, value);
                break;

            case "maxpoolsize":
                _maxPoolSize = ParseInt32(name, value);
                break;

            case "maxstaleness":
            case "maxstalenessseconds":
                _maxStaleness = ParseTimeSpan(name, value);
                if (_maxStaleness.Value == TimeSpan.FromSeconds(-1))
                {
                    _maxStaleness = null;
                }
                break;

            case "minpoolsize":
                _minPoolSize = ParseInt32(name, value);
                break;

            case "readconcernlevel":
                _readConcernLevel = ParseEnum <ReadConcernLevel>(name, value);
                break;

            case "readpreference":
                _readPreference = ParseEnum <ReadPreferenceMode>(name, value);
                break;

            case "readpreferencetags":
                var tagSet = ParseReadPreferenceTagSets(name, value);
                if (_readPreferenceTags == null)
                {
                    _readPreferenceTags = new List <TagSet> {
                        tagSet
                    }.AsReadOnly();
                }
                else
                {
                    _readPreferenceTags = _readPreferenceTags.Concat(new[] { tagSet }).ToList();
                }
                break;

            case "replicaset":
                _replicaSet = value;
                break;

            case "safe":
                var safe = ParseBoolean(name, value);
                if (_w == null)
                {
                    _w = safe ? 1 : 0;
                }
                else
                {
                    if (safe)
                    {
                        // don't overwrite existing W value unless it's 0
                        var wCount = _w as WriteConcern.WCount;
                        if (wCount != null && wCount.Value == 0)
                        {
                            _w = 1;
                        }
                    }
                    else
                    {
                        _w = 0;
                    }
                }
                break;

            case "localthreshold":
            case "localthresholdms":
            case "secondaryacceptablelatency":
            case "secondaryacceptablelatencyms":
                _localThreshold = ParseTimeSpan(name, value);
                break;

            case "slaveok":
                if (_readPreference != null)
                {
                    throw new MongoConfigurationException("ReadPreference has already been configured.");
                }
                _readPreference = ParseBoolean(name, value) ?
                                  ReadPreferenceMode.SecondaryPreferred :
                                  ReadPreferenceMode.Primary;
                break;

            case "serverselectiontimeout":
            case "serverselectiontimeoutms":
                _serverSelectionTimeout = ParseTimeSpan(name, value);
                break;

            case "sockettimeout":
            case "sockettimeoutms":
                _socketTimeout = ParseTimeSpan(name, value);
                break;

            case "ssl":
                _ssl = ParseBoolean(name, value);
                break;

            case "sslverifycertificate":
                _sslVerifyCertificate = ParseBoolean(name, value);
                break;

            case "guids":
            case "uuidrepresentation":
                _uuidRepresentation = ParseEnum <GuidRepresentation>(name, value);
                break;

            case "w":
                _w = WriteConcern.WValue.Parse(value);
                break;

            case "wtimeout":
            case "wtimeoutms":
                _wTimeout = ParseTimeSpan(name, value);
                if (_wTimeout < TimeSpan.Zero)
                {
                    throw new MongoConfigurationException($"{name} must be greater than or equal to 0.");
                }
                break;

            case "waitqueuemultiple":
                _waitQueueMultiple = ParseDouble(name, value);
                break;

            case "waitqueuesize":
                _waitQueueSize = ParseInt32(name, value);
                break;

            case "waitqueuetimeout":
            case "waitqueuetimeoutms":
                _waitQueueTimeout = ParseTimeSpan(name, value);
                break;

            default:
                _unknownOptions.Add(name, value);
                break;
            }
        }
Exemple #7
0
        /// <summary>
        /// Instantiates the object that holds the credentials for accessing SQL Servers
        /// containing the shard map manager data.
        /// </summary>
        /// <param name="connectionInfo">
        /// Connection info for shard map manager data source.
        /// </param>
        public SqlShardMapManagerCredentials(SqlConnectionInfo connectionInfo)
        {
            ExceptionUtils.DisallowNullArgument(connectionInfo, "connectionInfo");

            // Devnote: If connection string specifies Active Directory authentication and runtime is not
            // .NET 4.6 or higher, then below call will throw.
            SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(connectionInfo.ConnectionString);

            #region GSM Validation

            // DataSource must be set.
            if (string.IsNullOrEmpty(connectionStringBuilder.DataSource))
            {
                throw new ArgumentException(
                          StringUtils.FormatInvariant(
                              Errors._SqlShardMapManagerCredentials_ConnectionStringPropertyRequired,
                              "DataSource"),
                          "connectionString");
            }

            // InitialCatalog must be set.
            if (string.IsNullOrEmpty(connectionStringBuilder.InitialCatalog))
            {
                throw new ArgumentException(
                          StringUtils.FormatInvariant(
                              Errors._SqlShardMapManagerCredentials_ConnectionStringPropertyRequired,
                              "Initial Catalog"),
                          "connectionString");
            }

            // Ensure credentials are specified for GSM connectivity.
            SqlShardMapManagerCredentials.EnsureCredentials(
                connectionStringBuilder,
                "connectionString",
                connectionInfo.Credential,
                connectionInfo.AccessTokenFactory);

            #endregion GSM Validation

            // Generate connectionInfoShardMapManager
            SqlConnectionStringBuilder connectionStringShardMapManager = new SqlConnectionStringBuilder(connectionStringBuilder.ConnectionString);

            connectionStringShardMapManager.ApplicationName = ApplicationNameHelper.AddApplicationNameSuffix(
                connectionStringShardMapManager.ApplicationName,
                GlobalConstants.ShardMapManagerInternalConnectionSuffixGlobal);

            _smmDataSource     = connectionStringShardMapManager.DataSource;
            _smmInitialCatalog = connectionStringShardMapManager.InitialCatalog;

            this.ConnectionInfoShardMapManager =
                connectionInfo.CloneWithUpdatedConnectionString(connectionStringShardMapManager.ConnectionString);

            // Generate connectionInfoShard
            SqlConnectionStringBuilder connectionStringShard = new SqlConnectionStringBuilder(connectionStringBuilder.ConnectionString);

            connectionStringShard.Remove("Data Source");
            connectionStringShard.Remove("Initial Catalog");

            connectionStringShard.ApplicationName = ApplicationNameHelper.AddApplicationNameSuffix(
                connectionStringShard.ApplicationName,
                GlobalConstants.ShardMapManagerInternalConnectionSuffixLocal);

            this.ConnectionInfoShard =
                connectionInfo.CloneWithUpdatedConnectionString(connectionStringShard.ConnectionString);
        }