/// <summary>
        /// Performs the recent tweets from the Twitter API for each dashboard.
        /// </summary>
        /// <param name="id">The job identifier.</param>
        /// <returns>An instance of <see cref="Task"/>.</returns>
        protected override async Task TaskActionAsync(Guid?id)
        {
            var parameters = new Dictionary <string, object>();

            parameters.Add("Method", "TaskActionAsync");
            if (id.HasValue)
            {
                parameters.Add("Job ID", id);
            }

            _logger.LogWithParameters(LogLevel.Information, "Start importing recent tweets from Twitter API", parameters);

            using (var scope = _serviceProvider.CreateScope())
            {
                // Gets the services freom the scope.
                var dashboardService      = scope.ServiceProvider.GetService <IDashboardService>();
                var dashboardTweetService = scope.ServiceProvider.GetService <IDashboardTweetService>();
                var authorService         = scope.ServiceProvider.GetService <IAuthorService>();
                var tweetService          = scope.ServiceProvider.GetService <ITweetService>();
                var blashDbContext        = scope.ServiceProvider.GetService <BlashDbContext>();

                var maxResults = _apiConfiguration.Value.Tweets.MaxPerDashboard.HasValue ? _apiConfiguration.Value.Tweets.MaxPerDashboard.Value : 100;

                var updatedTweetIds = new List <int>();

                List <Dashboard> dashboards = null;

                using (var dbContextTransaction = await blashDbContext.Database.BeginTransactionAsync())
                {
                    _logger.LogWithParameters(LogLevel.Debug, "Get all dashboards from database", parameters);
                    dashboards = _dashboard != null ? new List <Dashboard> {
                        _dashboard
                    } : await dashboardService.GetAllAsync();                                                                    // Get all dashboards (or one if we have specified a dashboard).

                    _logger.LogWithParameters(LogLevel.Debug, string.Format("{0} dashboard{1} returned from the database", dashboards.Count, dashboards.Count() != 1 ? "s" : ""), parameters);

                    foreach (var dashboard in dashboards)
                    {
                        _logger.LogWithParameters(LogLevel.Information, "Start importing recent tweets for dashboard", parameters);

                        TweetResult recentTweets = null;


                        var recentTweetSearchParameters = new Dictionary <string, object>();
                        foreach (var param in parameters)
                        {
                            recentTweetSearchParameters.Add(param.Key, param.Value);
                        }
                        recentTweetSearchParameters.Add("Search Query", dashboard.SearchQuery);
                        recentTweetSearchParameters.Add("MaxResults", maxResults);

                        // Get recent tweets based on the dashboard's search query.
                        _logger.LogWithParameters(LogLevel.Debug, "Get recent tweets from Twitter API.", recentTweetSearchParameters);
                        try
                        {
                            recentTweets = await _twitterApiTweetService.GetRecentTweetsAsync(dashboard.SearchQuery, maxResults);
                        }
                        catch (Exception)
                        {
                            // Set as null if the API throws an exception.
                            recentTweets = null;
                        }
                        _logger.LogWithParameters(LogLevel.Debug, string.Format("{0} recent tweet{1} returned from the Twitter API.", recentTweets != null && recentTweets.Tweets != null ? recentTweets.Tweets.Count : "0", recentTweets == null || recentTweets.Tweets == null || recentTweets.Tweets.Count() != 1 ? "s" : ""), recentTweetSearchParameters);

                        if (recentTweets == null || recentTweets.Tweets == null || recentTweets.Tweets.Count == 0)
                        {
                            continue;
                        }

                        foreach (var recentTweet in recentTweets.Tweets)
                        {
                            // Go through each tweet returned from the Twitter API.
                            var recentTweetParameters = new Dictionary <string, object>();
                            foreach (var param in recentTweetSearchParameters)
                            {
                                recentTweetParameters.Add(param.Key, param.Value);
                            }
                            recentTweetParameters.Add("Twitter API Tweet Id", recentTweet.Id);

                            _logger.LogWithParameters(LogLevel.Information, "Start importing tweet", recentTweetParameters);

                            if (recentTweet.ReferencedTweets != null && recentTweet.ReferencedTweets.Count > 0)
                            {
                                continue;
                            }

                            // Does tweet exist in the databse.
                            var tweet = await TaskExtensions.CreateUpdateTweetAsync(scope, _logger, recentTweet, recentTweets.Includes.Users, recentTweets.Includes.Media);

                            if (tweet == null)
                            {
                                continue;
                            }

                            // Keep a list of all the updated tweets.
                            updatedTweetIds.Add(tweet.Id);

                            // Update the dashboard & tweet relationship in the database.
                            await TaskExtensions.CreateDashboardTweetRelationshipAsync(scope, _logger, dashboard.Id, tweet.Id);

                            _logger.LogWithParameters(LogLevel.Debug, string.Format("Tweet has been added to Dashboard (id: '{0}').", dashboard.Id), recentTweetParameters);

                            _logger.LogWithParameters(LogLevel.Information, "Finish importing tweet", recentTweetParameters);
                        }
                    }
                    // Commit the transaction.
                    await dbContextTransaction.CommitAsync();
                }


                // Delete any tweets that have not been updated.
                if (_dashboard == null)
                {
                    using (var dbContextTransaction = blashDbContext.Database.BeginTransaction())
                    {
                        await dashboardTweetService.DeleteNonUpdatedTweetsAsync(updatedTweetIds); // Remove non-updated dashboard & tweet relationships.

                        await tweetService.DeleteMissingTweetsFromDashboardAsync();               // Delete any tweets that don't belong to a dashboard.

                        await authorService.DeleteMissingTweetsAsync();                           // Delete any authors that don't belong to any tweets.

                        await dbContextTransaction.CommitAsync();                                 // Commit the transaction to the database.
                    }
                }

                // Send the updated information to the clients connected through SignalR
                await _blashHub.RecentTweetsSyncAsync(await ApiExtensions.GetDashboardAndTweetsAsync(dashboards, tweetService), _dashboard == null, _cancellationToken);
            }


            _logger.LogWithParameters(LogLevel.Information, "Finish importing recent tweets from Twitter API", parameters);
        }