/// <summary>
        /// Gets the database connection string.
        /// </summary>
        /// <param name="config">The config.</param>
        /// <returns></returns>
        internal static string GetDatabaseConnectionString(MongoDbWebSection mongoDbWebSection, NameValueCollection config)
        {
            string connectionString = GetConnectionString(mongoDbWebSection, config);
            var    builder          = new MongoUrlBuilder(connectionString);

            builder.DatabaseName = GetDatabaseName(mongoDbWebSection, connectionString, config);

            return(builder.ToString());
        }
        /// <summary>
        /// Gets the name of the database.
        /// </summary>
        /// <param name="connectionString">The connection string.</param>
        /// <param name="config">The config.</param>
        /// <returns></returns>
        internal static string GetDatabaseName(MongoDbWebSection mongoDbWebSection, string connectionString, NameValueCollection config)
        {
            MongoUrl mongoUrl = MongoUrl.Create(connectionString);

            if (!string.IsNullOrEmpty(mongoUrl.DatabaseName))
            {
                return(mongoUrl.DatabaseName);
            }

            return((mongoDbWebSection != null)
                ? mongoDbWebSection.DatabaseName
                : config["database"] ?? "ASPNETDB");
        }
        /// <summary>
        /// Gets the configured connection string.
        /// </summary>
        /// <param name="config">The config.</param>
        /// <returns></returns>
        internal static string GetConnectionString(MongoDbWebSection mongoDbWebSection, NameValueCollection config)
        {
            string connectionString = config["connectionString"];

            if (!string.IsNullOrWhiteSpace(connectionString))
            {
                return(connectionString);
            }

            string appSettingsKey = config["connectionStringKey"];

            if (string.IsNullOrWhiteSpace(appSettingsKey))
            {
                return((mongoDbWebSection != null) ? mongoDbWebSection.ConnectionString : "mongodb://localhost");
            }
            else
            {
                return(ConfigurationManager.ConnectionStrings[appSettingsKey].ConnectionString);
            }
        }
        public override void Initialize(string name, NameValueCollection config)
        {
            this._SessionStateSection = ConfigurationManager.GetSection("system.web/sessionState") as SessionStateSection;
            this._MongoWebSection     = ConfigurationManager.GetSection("mongoDbWeb") as MongoDbWebSection;

            this._MongoCollection = ConnectionHelper.GetDatabase(config)
                                    .GetCollection <T>(config["collection"] ?? _MongoWebSection.SessionState.MongoCollectionName);

            _SessionDataClassMap = new BsonClassMap <T>();
            _SessionDataClassMap.AutoMap();

            _ApplicationVirtualPathField = MapBsonMember(t => t.ApplicationVirtualPath);
            _IdField                  = MapBsonMember(t => t.SessionId);
            _LockIdField              = MapBsonMember(t => t.LockId);
            _LockedField              = MapBsonMember(t => t.Locked);
            _ExpiresField             = MapBsonMember(t => t.Expires);
            _LockDateField            = MapBsonMember(t => t.LockDate);
            _SessionStateActionsField = MapBsonMember(t => t.SessionStateActions);
            _SessionItemsField        = MapBsonMember(t => t.SessionStateItems);

            // Ideally, we'd just use the object's bson id - however, serialization gets a bit wonky
            // when trying to have an Id property which isn't a simple type in the base class
            // This also provides better backwards compatibility with the old BsonDocument implementation (field names match)
            this._MongoCollection.EnsureIndex(
                IndexKeys.Ascending(_ApplicationVirtualPathField, _IdField), IndexOptions.SetUnique(true));

            if (_Cache == null)
            {
                lock (_CacheGuarantee)
                {
                    if (_Cache == null)
                    {
                        _Cache = new Cache <string, T> .Builder()
                        {
                            EntryExpiration = new TimeSpan(0, 0, _MongoWebSection.SessionState.MemoryCacheExpireSeconds),
                            MaxEntries      = _MongoWebSection.SessionState.MaxInMemoryCachedSessions
                        }

                        .Cache;
                    }
                }
            }

            // Initialise safe mode options. Defaults to Safe Mode=true, fsynch=false, w=0 (replicas to write to before returning)
            bool safeModeEnabled = true;

            bool fsync = _MongoWebSection.FSync;

            if (config["fsync"] != null)
            {
                bool.TryParse(config["fsync"], out fsync);
            }

            int replicasToWrite = _MongoWebSection.ReplicasToWrite;

            if ((config["replicasToWrite"] != null) && (!int.TryParse(config["replicasToWrite"], out replicasToWrite)))
            {
                throw new ProviderException("replicasToWrite must be a valid integer");
            }

            _SafeMode = SafeMode.Create(safeModeEnabled, fsync, replicasToWrite);

            base.Initialize(name, config);
        }
 /// <summary>
 /// Gets the name of the database.
 /// </summary>
 /// <param name="config">The config.</param>
 /// <returns></returns>
 internal static string GetDatabaseName(MongoDbWebSection mongoDbWebSection, NameValueCollection config)
 {
     return(GetDatabaseName(mongoDbWebSection, GetConnectionString(mongoDbWebSection, config), config));
 }
        public override void Initialize(string name, NameValueCollection config)
        {
            this._SessionStateSection = ConfigurationManager.GetSection("system.web/sessionState") as SessionStateSection;
            this._MongoWebSection     = ConfigurationManager.GetSection("mongoDbWeb") as MongoDbWebSection;

            var connectionString = ConnectionHelper.GetDatabaseConnectionString(_MongoWebSection, config);
            var databaseName     = ConnectionHelper.GetDatabaseName(_MongoWebSection, config);
            var collectionName   =
                _MongoWebSection != null &&
                _MongoWebSection.SessionState != null &&
                _MongoWebSection.SessionState.MongoCollectionName != null
                                ? _MongoWebSection.SessionState.MongoCollectionName
                                : config["collection"];

            this._MongoCollection = MongoServer.Create(connectionString)
                                    .GetDatabase(databaseName)
                                    .GetCollection <T>(collectionName);

            _UseLock = config["useLock"] == "true" ? true : _MongoWebSection.SessionState.UseLock;

            _DotNetMemoryCacheName = config["dotNetMemoryCacheName"] == null
                                ? _MongoWebSection.SessionState.DotNetMemoryCacheName
                                : config["dotNetMemoryCacheName"];

            _SessionDataClassMap = new BsonClassMap <T>();
            _SessionDataClassMap.AutoMap();

            _ApplicationVirtualPathField = MapBsonMember(t => t.ApplicationVirtualPath);
            _IdField                  = MapBsonMember(t => t.SessionId);
            _LockIdField              = MapBsonMember(t => t.LockId);
            _LockedField              = MapBsonMember(t => t.Locked);
            _AccessedField            = MapBsonMember(t => t.Accessed);
            _ExpiresField             = MapBsonMember(t => t.Expires);
            _LockDateField            = MapBsonMember(t => t.LockDate);
            _SessionStateActionsField = MapBsonMember(t => t.SessionStateActions);
            _SessionItemsField        = MapBsonMember(t => t.SessionStateItems);

            // Ideally, we'd just use the object's bson id - however, serialization gets a bit wonky
            // when trying to have an Id property which isn't a simple type in the base class
            // This also provides better backwards compatibility with the old BsonDocument implementation (field names match)
            this._MongoCollection.EnsureIndex(
                IndexKeys.Ascending(_ApplicationVirtualPathField, _IdField), IndexOptions.SetUnique(true));

            // MongoDB TTL collection http://docs.mongodb.org/manual/tutorial/expire-data/
            this._MongoCollection.EnsureIndex(IndexKeys.Ascending(_AccessedField), IndexOptions.SetTimeToLive(_SessionStateSection.Timeout));

            bool useDotNetMemoryCache = !string.IsNullOrWhiteSpace(_DotNetMemoryCacheName);

            if (useDotNetMemoryCache && _MemoryCache == null)
            {
                lock (_CacheGuarantee)
                {
                    if (_MemoryCache == null)
                    {
                        _MemoryCache = new MemoryCache(_DotNetMemoryCacheName);
                    }
                }
            }

            // Initialise safe mode options. Defaults to Safe Mode=true, fsynch=false, w=0 (replicas to write to before returning)
            bool safeModeEnabled = true;

            bool fsync = _MongoWebSection.FSync;

            if (config["fsync"] != null)
            {
                bool.TryParse(config["fsync"], out fsync);
            }

            int replicasToWrite = _MongoWebSection.ReplicasToWrite;

            if ((config["replicasToWrite"] != null) && (!int.TryParse(config["replicasToWrite"], out replicasToWrite)))
            {
                throw new ProviderException("replicasToWrite must be a valid integer");
            }

            _SafeMode = SafeMode.Create(safeModeEnabled, fsync, replicasToWrite);

            base.Initialize(name, config);
        }