/// <summary>
        /// Initializes a new instance of the <see cref="MongoRepository"/> class.
        /// </summary>
        public MongoRepository()
        {
            var connectionStringElement = ConfigurationManager.ConnectionStrings[ConnectionStringKey];
            Debug.Assert( connectionStringElement != null );

            string connectionString = connectionStringElement.ConnectionString;
            Debug.Assert( connectionString != null );

            var url = MongoUrl.Create( connectionString );
            _dataBaseName = url.DatabaseName;
            _dataBaseCredentials = url.DefaultCredentials;

            //InitializeClassMap();

            _server = MongoServer.Create( connectionString );
            _dataBase = GetDatabase();

            // Create additional index
            _dataBase.GetCollection( UserCollectionName )
                .EnsureIndex( FavoriteMoviesMovieIdFieldName );

            CurrentGeneratorOperationResult = new RepositoryOperationResult( NAOperationName );
        }
        private void RemoveAllUsersTask( RepositoryOperationResult state )
        {
            state.StartDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.InProcess;

            var allRegistredUsers = Membership.GetAllUsers();

            state.MaxIteration = allRegistredUsers.Count + 1;

            foreach (MembershipUser registredUser in allRegistredUsers)
            {
                Membership.DeleteUser( registredUser.UserName, true );
                state.IterationDone++;
            }

            var users = _dataBase.GetCollection( UserCollectionName );
            users.RemoveAll();
            state.IterationDone++;

            state.EndDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.Success;
        }
 /// <summary>
 /// Starts the task in background.
 /// </summary>
 /// <param name="action">The action.</param>
 /// <param name="operationName">Name of the operation.</param>
 /// <returns>Repository operation result object</returns>
 private RepositoryOperationResult StartTask( Action<object> action, string operationName )
 {
     if ((_generateUserRecordsTask == null || _generateUserRecordsTask.IsCompleted) &&
         (CurrentGeneratorOperationResult == null || CurrentGeneratorOperationResult.State != RepositoryOperationResultState.InProcess))
     {
         CurrentGeneratorOperationResult = new RepositoryOperationResult( operationName );
         _generateUserRecordsTask =
             Task.Factory.StartNew(
                 action,
                 CurrentGeneratorOperationResult,
                 TaskCreationOptions.LongRunning );
     }
     return CurrentGeneratorOperationResult;
 }
        private void RemoveAllActorsTask( RepositoryOperationResult state )
        {
            state.StartDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.InProcess;

            state.MaxIteration = 1;

            var actorCollection = _dataBase.GetCollection( ActorCollectionName );
            actorCollection.RemoveAll();

            state.IterationDone++;

            state.EndDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.Success;
        }
        private void RemoveAllMoviesTask( RepositoryOperationResult state )
        {
            state.StartDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.InProcess;

            state.MaxIteration = 1;

            var movieCollection = _dataBase.GetCollection( MovieCollectionName );
            movieCollection.RemoveAll();

            var userCollection = _dataBase.GetCollection( MovieCollectionName );
            // Remove all favorite movies
            userCollection.Update( Query.Null, Update.Unset( FavoriteMoviesFieldName ) );
            // Remove all friends favorite movies
            userCollection.Update( Query.Null, Update.Unset( FriendsFavoriteMoviesFieldName ) );

            state.IterationDone++;

            state.EndDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.Success;
        }
        private void GenerateUserRecordsTask( long quantity, RepositoryOperationResult state )
        {
            state.StartDateTime = DateTime.Now;
            state.MaxIteration = quantity;
            state.State = RepositoryOperationResultState.InProcess;

            var users = _dataBase.GetCollection( UserCollectionName );

            var lastNumber = FindLastNumber( users, NameFieldName, _userRegex ) + 1;

            var random = new Random();
            for (int i = 0; i < quantity; i++, lastNumber++)
            {
                var userModel = new RegisterModel
                                    {
                                        UserName = string.Format( DefaultUserNameFormat, lastNumber ),
                                        Age = random.Next( 91 ) + 10,
                                        Gender = (Gender)(random.Next( 2 ) + 1),
                                        Password = DefaultUserPassword,
                                    };

                userModel.Email = userModel.UserName + "@maildomain.com";

                var userMembership = Membership.GetUser( userModel.UserName );
                if (userMembership != null) Membership.DeleteUser( userModel.UserName );

                RegisterUser( userModel, false );

                state.IterationDone++;
            }

            state.EndDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.Success;
        }
        /// <summary>
        /// Generates the movie records. Task method.
        /// </summary>
        /// <param name="recordsNumber">The number of records.</param>
        /// <param name="state">The repository operation result state object.</param>
        private void GenerateMovieRecordsTask( long recordsNumber, RepositoryOperationResult state )
        {
            state.StartDateTime = DateTime.Now;
            state.MaxIteration = recordsNumber;
            state.State = RepositoryOperationResultState.InProcess;

            var movieCollection = _dataBase.GetCollection( MovieCollectionName );
            var actorCollection = _dataBase.GetCollection<Actor>( ActorCollectionName );
            var actorIds = actorCollection
                .FindAllAs<ActorId>()
                .SetFields( Fields.Include( IdFieldName ) )
                .ToList();

            var lastNumber = FindLastNumber( movieCollection, NameFieldName, _movieRegex ) + 1;

            for (int i = 0; i < recordsNumber; i++, lastNumber++)
            {
                var movie = new Movie
                {
                    Id = ObjectId.GenerateNewId(),
                    Name = string.Format( DefaultMovieNameFormat, lastNumber ),
                    Roles = GenerateRoles( MinRolesNumber, MaxRolesNumber, actorIds, actorCollection ),
                };

                movieCollection.Insert( movie );

                state.IterationDone++;
            }

            state.EndDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.Success;
        }
        private void GenerateFriendshipRelationsTask( int minFriendsNumber, int maxFriendsNumber, RepositoryOperationResult state )
        {
            state.StartDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.InProcess;

            var userCollection = _dataBase.GetCollection<User>( UserCollectionName );
            var userIds = userCollection
                .FindAllAs<UserId>()
                .SetFields( Fields.Include( IdFieldName ) )
                .ToList();

            state.MaxIteration = userIds.Count;

            int deltaFriendsNumber = maxFriendsNumber - minFriendsNumber;

            Random random = new Random();
            int iUser = 0;
            foreach (var userId in userIds)
            {
                User user = userCollection.FindOneById( userId.Id );
                int friendsNumber = random.Next( deltaFriendsNumber + 1 ) + minFriendsNumber;
                if (friendsNumber > userIds.Count - 1) friendsNumber = userIds.Count - 1;
                int iFriend = user.Friends.Count;
                while (iFriend < friendsNumber)
                {
                    int jUser = random.Next( userIds.Count );
                    if (iUser == jUser) continue;
                    var friendId = userIds[jUser].Id;
                    if (user.Friends.Any( userFriend => userFriend.UserId.Equals( friendId ) )) continue;

                    User friend = userCollection.FindOneById( friendId );
                    Debug.Assert( friend != null );

                    MakeFriends( user, friend, userCollection );
                    iFriend++;
                }
                iUser++;
                state.IterationDone++;
            }

            state.EndDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.Success;
        }
        private void GenerateFavoriteMoviesTask( int minFavoriteMoviesNumber, int maxFavoriteMoviesNumber, RepositoryOperationResult state )
        {
            state.StartDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.InProcess;

            var userCollection = _dataBase.GetCollection<User>( UserCollectionName );
            var userIds = userCollection
                .FindAllAs<UserId>()
                .SetFields( Fields.Include( IdFieldName ) )
                .ToList();

            var movieCollection = _dataBase.GetCollection<Movie>( MovieCollectionName );
            var movieIds = movieCollection
                .FindAllAs<MovieId>()
                .SetFields( Fields.Include( IdFieldName ) )
                .ToList();

            state.MaxIteration = userIds.Count;

            int deltaFavoriteMoviesNumber = maxFavoriteMoviesNumber - minFavoriteMoviesNumber;

            Random random = new Random();
            foreach (var userId in userIds)
            {
                User user = userCollection.FindOneById( userId.Id );
                int moviesNumber = random.Next( deltaFavoriteMoviesNumber + 1 ) + minFavoriteMoviesNumber;
                int iMovie = user.FavoriteMovies.Count;

                while (iMovie < moviesNumber)
                {
                    int jMovie = random.Next( movieIds.Count );
                    var movieId = movieIds[jMovie].Id;
                    if (user.FavoriteMovies.Any( m => m.MovieId.Equals( movieId ) )) continue;

                    Movie favoriteMovie = movieCollection.FindOneById( movieId );
                    Debug.Assert( favoriteMovie != null );

                    AddUserFavoriteMovie( user, favoriteMovie, userCollection );
                    iMovie++;
                }

                state.IterationDone++;
            }

            state.EndDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.Success;
        }
        private void GenerateActorRecordsTask( long quantity, RepositoryOperationResult state )
        {
            state.StartDateTime = DateTime.Now;
            state.MaxIteration = quantity;
            state.State = RepositoryOperationResultState.InProcess;

            var actorCollection = _dataBase.GetCollection( ActorCollectionName );

            var lastNumber = FindLastNumber( actorCollection, NameFieldName, _actorRegex ) + 1;

            for (int i = 0; i < quantity; i++, lastNumber++)
            {
                var actor = new Actor
                {
                    Id = ObjectId.GenerateNewId(),
                    Name = string.Format( DefaultActorNameFormat, lastNumber ),
                    Biography = string.Format( DefaultActorBiographyTextFormat, lastNumber ),
                };

                actorCollection.Insert( actor );

                state.IterationDone++;
            }

            state.EndDateTime = DateTime.Now;
            state.State = RepositoryOperationResultState.Success;
        }