//=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="component">The build component that owns the dictionary.  This is useful for logging
        /// messages during initialization.</param>
        /// <param name="configuration">The target dictionary configuration</param>
        /// <param name="connectionString">The connection string to use</param>
        /// <param name="groupId">The group ID to use</param>
        /// <param name="localCacheSize">The local cache size to use</param>
        /// <param name="reload">True to reload the cache or false to leave it alone.  This is used to reload
        /// project data so that it is always current.</param>
        /// <returns>A target dictionary instance that uses a simple in-memory
        /// <see cref="Dictionary{TKey, TValue}"/> instance to store the targets.</returns>
        public SqlTargetDictionary(BuildComponentCore component, XPathNavigator configuration,
          string connectionString, string groupId, int localCacheSize, bool reload) :
          base(component, configuration)
        {
            this.connectionString = connectionString;
            base.DictionaryId = groupId;

            index = new SqlDictionary<Target>(connectionString, "Targets", "TargetKey", "TargetValue",
              "GroupId", groupId)
            {
                LocalCacheSize = localCacheSize
            };

            int filesToLoad = 0;

            if(reload)
            {
                filesToLoad = Directory.EnumerateFiles(this.DirectoryPath, this.FilePattern, this.Recurse ?
                  SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).Count();
            }
            else
                foreach(string file in Directory.EnumerateFiles(this.DirectoryPath, this.FilePattern, this.Recurse ?
                  SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
                    if((this.NamespaceFileFilter.Count == 0 || this.NamespaceFileFilter.Contains(
                      Path.GetFileName(file))) && !this.ContainsKey("N:" + Path.GetFileNameWithoutExtension(file)))
                        filesToLoad++;

            // Loading new targets can take a while so issue a diagnostic message as an alert.  The time estimate
            // is a ballpark figure and depends on the system.
            if(filesToLoad != 0)
            {
                component.WriteMessage(MessageLevel.Diagnostic, "{0} file(s) need to be added to the SQL " +
                    "reflection target cache database.  Indexing them will take about {1:N0} minute(s), " +
                    "please be patient.  Cache location: {2}", filesToLoad, Math.Ceiling(filesToLoad / 60.0),
                    connectionString);

                this.LoadTargetDictionary();
            }
        }
        //=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="component">The build component that owns the dictionary.  This is useful for logging
        /// messages during initialization.</param>
        /// <param name="configuration">The target dictionary configuration</param>
        /// <returns>A target dictionary instance that uses a simple in-memory
        /// <see cref="Dictionary{TKey, TValue}"/> instance to store the targets.</returns>
        public ESentTargetDictionary(BuildComponentCore component, XPathNavigator configuration) :
          base(component, configuration)
        {
            bool noReload = false;
            int localCacheSize;

            string cachePath = configuration.GetAttribute("cachePath", String.Empty);

            if(String.IsNullOrWhiteSpace(cachePath))
                throw new ArgumentException("The cachePath attribute must contain a value", "configuration");

            string cacheSize = configuration.GetAttribute("localCacheSize", String.Empty);

            if(String.IsNullOrWhiteSpace(cacheSize) || !Int32.TryParse(cacheSize, out localCacheSize))
                localCacheSize = 1000;

            // This is a slightly modified version of Managed ESENT that provides the option to serialize
            // reference types.  In this case, we don't care about potential issues of persisted copies not
            // matching the original if modified as they are never updated once written to the cache.  We can
            // also turn off column compression for a slight performance increase since it doesn't benefit the
            // binary data that is serialized.
            PersistentDictionaryFile.AllowReferenceTypeSerialization = true;

            index = new PersistentDictionary<string, Target>(cachePath, false)
                { LocalCacheSize = localCacheSize };

            string noReloadValue = configuration.GetAttribute("noReload", String.Empty);

            // If noReload is true, skip reloading the dictionary if it contains any data.  This is used on
            // project targets to prevent reloading the data in the reference build if already loaded by the
            // conceptual build.
            if(!String.IsNullOrWhiteSpace(noReloadValue) && Boolean.TryParse(noReloadValue, out noReload) &&
              noReload && index.Count != 0)
                return;

            // Loading new targets can take a while so issue a diagnostic message as an alert
            int filesToLoad = 0;

            foreach(string file in Directory.EnumerateFiles(this.DirectoryPath, this.FilePattern, this.Recurse ?
              SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
                if((this.NamespaceFileFilter.Count == 0 || this.NamespaceFileFilter.Contains(
                  Path.GetFileName(file))) && !this.ContainsKey("N:" + Path.GetFileNameWithoutExtension(file)))
                    filesToLoad++;

            // The time estimate is a ballpark figure and depends on the system
            if(filesToLoad != 0)
            {
                component.WriteMessage(MessageLevel.Diagnostic, "{0} file(s) need to be added to the ESENT " +
                    "reflection target cache database.  Indexing them will take about {1:N0} minute(s), " +
                    "please be patient.  Cache location: {2}", filesToLoad, Math.Ceiling(filesToLoad * 10 / 60.0),
                    cachePath);

                // Limit the degree of parallelism or it overwhelms the ESENT version store
                this.LoadTargetDictionary(3);
            }
        }