private async void loginButton_Click(object sender, EventArgs e)
        {
            var agent = this.sqlAgentsComboBox.SelectedValue as SqlAgentBase;

            if (agent == null)
            {
                MessageBox.Show("Agent type not specified.", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (agent.IsFileBased && databaseTextBox.Text.IsNullOrWhiteSpace())
            {
                MessageBox.Show("Database file not specified.", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            try
            {
                ISqlDictionary dictionary = null;
                if (this.useSqlRepositoryCheckBox.Checked)
                {
                    dictionary = new SqlDictionary(this.sqlRepositoryFolderTextBox.Text, true);
                }
                _agent = (SqlAgentBase)Activator.CreateInstance(agent.GetType(),
                                                                this.connectionStringTextBox.Text, this.databaseTextBox.Text, dictionary, null);
                await _agent.TestConnectionAsync();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            this.DialogResult = DialogResult.OK;
            this.Close();
        }
        private static SqlDictionary <string, string> CreateDictionary(out IDictionary <string, string> inner)
        {
            inner = new Dictionary <string, string>();
            inner.Add("key1", "value1");
            var server = new FakeSqlServer <string, string>(inner);
            var dic    = new SqlDictionary <string, string>(server);

            dic.Load("SOMECONNECTIONSTRING", "SOMETABLE", "Key", "Value");
            return(dic);
        }
Esempio n. 3
0
        //=====================================================================

        /// <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();
            }
        }
Esempio n. 4
0
        public static SqlDictionary LoadDefaultSqlDictionary()
        {
            var dict = new SqlDictionary();
            var assembly = Assembly.GetExecutingAssembly();
            var types = assembly.GetTypes().Where(t=>t.GetInterfaces().Contains(typeof(ISymbolRegister))); 
            foreach(Type type in types)
            {
                var register = (ISymbolRegister)Activator.CreateInstance(type);
                var sqlMakers = new Dictionary<string,ISqlMaker>();
                register.RegistSQL(sqlMakers);
                dict[register.dbType] = sqlMakers;
            }

            if (App.CustomSqlRegister !=null)
                App.CustomSqlRegister(dict);

            return dict;
        }
Esempio n. 5
0
        //=====================================================================

        /// <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();
            }
        }
Esempio n. 6
0
        static void Main(string[] args)
        {
            string connectionString = null;
            string tableName        = null;
            string keyName          = null;
            string valueName        = null;

            var parser = new Fclp.FluentCommandLineParser();

            parser.Setup <string>('c', "connectionString").Callback(x => connectionString = x);
            parser.Setup <string>('t', "tableName").Callback(x => tableName = x);
            parser.Setup <string>('k', "key").Callback(x => keyName         = x);
            parser.Setup <string>('v', "value").Callback(x => valueName     = x);
            parser.Parse(args);

            Console.WriteLine("Connecting...");

            var dic1 = new SqlDictionary <int, int>();

            dic1.Load(connectionString, "intint", keyName, valueName);
            Console.WriteLine("SqlDictionary.Clear");
            dic1.Clear();
            Console.WriteLine("dic1.Count == 0");
            Debug.Assert(dic1.Count == 0);
            dic1.Add(1, 2);
            Console.WriteLine("dic1.Count == 1");
            Debug.Assert(dic1.Count == 1);
            Console.WriteLine("dic1[1] == 2");
            Debug.Assert(dic1[1] == 2);
            dic1.Remove(1);
            Console.WriteLine("dic1.Count == 0");
            Debug.Assert(dic1.Count == 0);
            dic1[1] = 3;
            Console.WriteLine("dic1[1] == 3");
            Debug.Assert(dic1[1] == 3);
            dic1[1] = 4;
            Console.WriteLine("dic1[1] == 4");
            Debug.Assert(dic1[1] == 4);

            var dic2 = new SqlDictionary <int, string>();

            dic2.Load(connectionString, "intstring", keyName, valueName);
            dic2.Clear();
            dic2.Add(1, "2");
            dic2.Remove(1);
            dic2[1] = "3";
            dic2[1] = "4";

            var dic3 = new SqlDictionary <string, string>();

            dic3.Load(connectionString, "stringstring", keyName, valueName);
            dic3.Clear();
            dic3.Add("1", "2");
            dic3.Remove("1");
            dic3["1"] = "3";
            dic3["1"] = "4";

            var dic4 = new SqlDictionary <string, SomeDto>();

            dic4.Load(connectionString, "stringdto", keyName, valueName);
            dic4.Clear();
            dic4.Add("1", new SomeDto()
            {
                Id = 1, Name = "SomeName"
            });
            dic4.Remove("1");
            dic4["1"] = new SomeDto()
            {
                Id = 2, Name = "SomeName"
            };
            dic4["1"] = new SomeDto()
            {
                Id = 3, Name = "SomeName"
            };


            var dic5 = new SqlNoMemoryDictionary <int, int>();

            dic5.Prepare(connectionString, "lazyintint", keyName, valueName);
            dic5.Clear();
            dic5.Add(1, 2);
            dic5.Remove(1);
            dic5[1] = 3;
            dic5[1] = 4;

            Console.WriteLine("OK!");
        }
Esempio n. 7
0
        //=====================================================================

        /// <summary>
        /// This is used to create the index cache
        /// </summary>
        /// <param name="configuration">The configuration to use</param>
        private SqlDictionary<string> CreateCache(XPathNavigator configuration)
        {
            SqlDictionary<string> cache = null;
            HashSet<string> namespaceFileFilter = new HashSet<string>();
            string groupId, connectionString, baseDirectory, wildcardPath, recurseValue, dupWarning, fullPath,
                directoryPart, filePart;
            bool recurse, reportDuplicateIds, cacheProject, isProjectData = false;
            int localCacheSize, filesToLoad;

            var parent = configuration.Clone();
            parent.MoveToParent();

            connectionString = parent.GetAttribute("connectionString", String.Empty);
            groupId = configuration.GetAttribute("groupId", String.Empty);

            // If caching project data, they will all go into a common index
            if(groupId.StartsWith("Project_", StringComparison.OrdinalIgnoreCase))
                isProjectData = true;

            cache = sqlCaches.FirstOrDefault(c => c.GroupId == groupId);

            if(cache == null)
            {
                if(!Boolean.TryParse(parent.GetAttribute("cacheProject", String.Empty), out cacheProject))
                    cacheProject = false;

                if((isProjectData && !cacheProject) || String.IsNullOrWhiteSpace(connectionString))
                    return null;

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

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

                cache = new SqlDictionary<string>(connectionString, "IndexData", "IndexKey", "IndexValue",
                  "GroupId", groupId)
                {
                    LocalCacheSize = localCacheSize
                };
            }

            baseDirectory = configuration.GetAttribute("base", String.Empty);

            if(!String.IsNullOrWhiteSpace(baseDirectory))
                baseDirectory = Environment.ExpandEnvironmentVariables(baseDirectory);

            wildcardPath = configuration.GetAttribute("files", String.Empty);

            if(String.IsNullOrWhiteSpace(wildcardPath))
                base.Component.WriteMessage(MessageLevel.Error, "Each data element must have a files attribute " +
                    "specifying which files to index.");

            wildcardPath = Environment.ExpandEnvironmentVariables(wildcardPath);

            recurseValue = configuration.GetAttribute("recurse", String.Empty);

            if(String.IsNullOrWhiteSpace(recurseValue) || !Boolean.TryParse(recurseValue, out recurse))
                recurse = false;

            // Support suppression of duplicate ID warnings.  This can happen a lot when common classes appear in
            // multiple assemblies.
            dupWarning = configuration.GetAttribute("duplicateWarning", String.Empty);

            if(String.IsNullOrWhiteSpace(dupWarning) || !Boolean.TryParse(dupWarning, out reportDuplicateIds))
                reportDuplicateIds = true;

            if(String.IsNullOrEmpty(baseDirectory))
                fullPath = wildcardPath;
            else
            {
                // Verify that the directory exists
                if(!Directory.Exists(baseDirectory))
                    throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The targets " +
                        "directory '{0}' does not exist.  The configuration is most likely out of date.  " +
                        "Please delete this component from the project, add it back, and reconfigure it.",
                        baseDirectory), "configuration");

                fullPath = Path.Combine(baseDirectory, wildcardPath);
            }

            fullPath = Environment.ExpandEnvironmentVariables(fullPath);

            directoryPart = Path.GetDirectoryName(fullPath);

            if(String.IsNullOrEmpty(directoryPart))
                directoryPart = Environment.CurrentDirectory;

            filePart = Path.GetFileName(fullPath);

            // Filtering reduces the number of files to load, especially for the core reflection data files
            namespaceFileFilter.Clear();

            foreach(XPathNavigator filter in configuration.Select("namespace/@file"))
                namespaceFileFilter.Add(filter.Value);

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

            if(namespaceFileFilter.Count != 0)
            {
                // Reflection data can be filtered by namespace so some or all of it may already be there
                foreach(string file in Directory.EnumerateFiles(directoryPart, filePart, recurse ?
                  SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
                    if((namespaceFileFilter.Count == 0 || namespaceFileFilter.Contains(Path.GetFileName(file))) &&
                      !cache.ContainsKey("N:" + Path.GetFileNameWithoutExtension(file)))
                        filesToLoad++;
            }
            else
            {
                // Comments files can't be filtered by namespace so we'll assume that if the collection is not
                // empty, it has already been loaded unless it's a project comments file list.  In that case,
                // we will merge them if necessary.
                if(isProjectData || cache.Count == 0)
                    filesToLoad = Directory.EnumerateFiles(directoryPart, filePart, recurse ?
                        SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).Count();
            }

            if(filesToLoad != 0)
            {
                // The time estimate is a ballpark figure and depends on the system
                base.Component.WriteMessage(MessageLevel.Diagnostic, "{0} file(s) need to be added to the SQL " +
                    "index cache database.  Indexing them will take about {1:N0} minute(s), please be " +
                    "patient.  Group ID: {2}  Cache location: {3}", filesToLoad, Math.Ceiling(filesToLoad / 60.0),
                    groupId, connectionString);

                Parallel.ForEach(Directory.EnumerateFiles(directoryPart, filePart,
                    recurse ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly),
                    file =>
                    {
                        // Skip the file if not in a defined filter
                        if(namespaceFileFilter.Count != 0 && !namespaceFileFilter.Contains(Path.GetFileName(file)))
                            return;

                        base.Component.WriteMessage(MessageLevel.Info, "Indexing targets in {0}", file);

                        using(SqlConnection cn = new SqlConnection(connectionString))
                        using(SqlCommand cmdSearch = new SqlCommand())
                        using(SqlCommand cmdAdd = new SqlCommand())
                        {
                            cn.Open();

                            cmdSearch.Connection = cmdAdd.Connection = cn;

                            cmdSearch.CommandText = String.Format(CultureInfo.InvariantCulture,
                                "Select IndexKey From IndexData Where GroupId = '{0}' And IndexKey = @key",
                                groupId);
                            cmdSearch.Parameters.Add(new SqlParameter("@key", SqlDbType.VarChar, 768));

                            cmdAdd.CommandText = String.Format(CultureInfo.InvariantCulture,
                                "IF NOT EXISTS(Select * From IndexData Where GroupId = '{0}' And IndexKey = @key) " +
                                "Insert IndexData (GroupId, IndexKey, IndexValue) Values('{0}', @key, @value) " +
                                "ELSE " +
                                "Update IndexData Set IndexValue = @value Where GroupId = '{0}' And IndexKey = @key",
                                groupId);

                            cmdAdd.Parameters.Add(new SqlParameter("@key", SqlDbType.VarChar, 768));
                            cmdAdd.Parameters.Add(new SqlParameter("@value", SqlDbType.Text));

                            // Get the keys from the file and add them to the index
                            foreach(var kv in base.GetValues(file))
                            {
                                cmdSearch.Parameters[0].Value = cmdAdd.Parameters[0].Value = kv.Key;

                                // Only report the warning if wanted
                                if(cmdSearch.ExecuteScalar() != null && reportDuplicateIds)
                                    this.Component.WriteMessage(MessageLevel.Warn, "An entry for the key '{0}' " +
                                        "already exists and will be replaced by the one from '{1}'", kv.Key, file);

                                cmdAdd.Parameters[1].Value = kv.Value.InnerXml;
                                cmdAdd.ExecuteNonQuery();
                            }
                        }
                    });
            }

            return cache;
        }
Esempio n. 8
0
        //=====================================================================

        /// <summary>
        /// This is used to create the index cache
        /// </summary>
        /// <param name="configuration">The configuration to use</param>
        private SqlDictionary <string> CreateCache(XPathNavigator configuration)
        {
            SqlDictionary <string> cache = null;
            HashSet <string>       namespaceFileFilter = new HashSet <string>();
            string groupId, connectionString, baseDirectory, wildcardPath, recurseValue, dupWarning, fullPath,
                   directoryPart, filePart;
            bool recurse, reportDuplicateIds, cacheProject, isProjectData = false;
            int  localCacheSize, filesToLoad;

            var parent = configuration.Clone();

            parent.MoveToParent();

            connectionString = parent.GetAttribute("connectionString", String.Empty);
            groupId          = configuration.GetAttribute("groupId", String.Empty);

            // If caching project data, they will all go into a common index
            if (groupId.StartsWith("Project_", StringComparison.OrdinalIgnoreCase))
            {
                isProjectData = true;
            }

            cache = sqlCaches.FirstOrDefault(c => c.GroupId == groupId);

            if (cache == null)
            {
                if (!Boolean.TryParse(parent.GetAttribute("cacheProject", String.Empty), out cacheProject))
                {
                    cacheProject = false;
                }

                if ((isProjectData && !cacheProject) || String.IsNullOrWhiteSpace(connectionString))
                {
                    return(null);
                }

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

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

                cache = new SqlDictionary <string>(connectionString, "IndexData", "IndexKey", "IndexValue",
                                                   "GroupId", groupId)
                {
                    LocalCacheSize = localCacheSize
                };
            }

            baseDirectory = configuration.GetAttribute("base", String.Empty);

            if (!String.IsNullOrWhiteSpace(baseDirectory))
            {
                baseDirectory = Environment.ExpandEnvironmentVariables(baseDirectory);
            }

            wildcardPath = configuration.GetAttribute("files", String.Empty);

            if (String.IsNullOrWhiteSpace(wildcardPath))
            {
                base.Component.WriteMessage(MessageLevel.Error, "Each data element must have a files attribute " +
                                            "specifying which files to index.");
            }

            wildcardPath = Environment.ExpandEnvironmentVariables(wildcardPath);

            recurseValue = configuration.GetAttribute("recurse", String.Empty);

            if (String.IsNullOrWhiteSpace(recurseValue) || !Boolean.TryParse(recurseValue, out recurse))
            {
                recurse = false;
            }

            // Support suppression of duplicate ID warnings.  This can happen a lot when common classes appear in
            // multiple assemblies.
            dupWarning = configuration.GetAttribute("duplicateWarning", String.Empty);

            if (String.IsNullOrWhiteSpace(dupWarning) || !Boolean.TryParse(dupWarning, out reportDuplicateIds))
            {
                reportDuplicateIds = true;
            }

            if (String.IsNullOrEmpty(baseDirectory))
            {
                fullPath = wildcardPath;
            }
            else
            {
                // Verify that the directory exists
                if (!Directory.Exists(baseDirectory))
                {
                    throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The targets " +
                                                              "directory '{0}' does not exist.  The configuration is most likely out of date.  " +
                                                              "Please delete this component from the project, add it back, and reconfigure it.",
                                                              baseDirectory), "configuration");
                }

                fullPath = Path.Combine(baseDirectory, wildcardPath);
            }

            fullPath = Environment.ExpandEnvironmentVariables(fullPath);

            directoryPart = Path.GetDirectoryName(fullPath);

            if (String.IsNullOrEmpty(directoryPart))
            {
                directoryPart = Environment.CurrentDirectory;
            }

            filePart = Path.GetFileName(fullPath);

            // Filtering reduces the number of files to load, especially for the core reflection data files
            namespaceFileFilter.Clear();

            foreach (XPathNavigator filter in configuration.Select("namespace/@file"))
            {
                namespaceFileFilter.Add(filter.Value);
            }

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

            if (namespaceFileFilter.Count != 0)
            {
                // Reflection data can be filtered by namespace so some or all of it may already be there
                foreach (string file in Directory.EnumerateFiles(directoryPart, filePart, recurse ?
                                                                 SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
                {
                    if ((namespaceFileFilter.Count == 0 || namespaceFileFilter.Contains(Path.GetFileName(file))) &&
                        !cache.ContainsKey("N:" + Path.GetFileNameWithoutExtension(file)))
                    {
                        filesToLoad++;
                    }
                }
            }
            else
            {
                // Comments files can't be filtered by namespace so we'll assume that if the collection is not
                // empty, it has already been loaded unless it's a project comments file list.  In that case,
                // we will merge them if necessary.
                if (isProjectData || cache.Count == 0)
                {
                    filesToLoad = Directory.EnumerateFiles(directoryPart, filePart, recurse ?
                                                           SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).Count();
                }
            }

            if (filesToLoad != 0)
            {
                // The time estimate is a ballpark figure and depends on the system
                base.Component.WriteMessage(MessageLevel.Diagnostic, "{0} file(s) need to be added to the SQL " +
                                            "index cache database.  Indexing them will take about {1:N0} minute(s), please be " +
                                            "patient.  Group ID: {2}  Cache location: {3}", filesToLoad, Math.Ceiling(filesToLoad / 60.0),
                                            groupId, connectionString);

                Parallel.ForEach(Directory.EnumerateFiles(directoryPart, filePart,
                                                          recurse ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly),
                                 file =>
                {
                    // Skip the file if not in a defined filter
                    if (namespaceFileFilter.Count != 0 && !namespaceFileFilter.Contains(Path.GetFileName(file)))
                    {
                        return;
                    }

                    base.Component.WriteMessage(MessageLevel.Info, "Indexing targets in {0}", file);

                    using (SqlConnection cn = new SqlConnection(connectionString))
                        using (SqlCommand cmdSearch = new SqlCommand())
                            using (SqlCommand cmdAdd = new SqlCommand())
                            {
                                cn.Open();

                                cmdSearch.Connection = cmdAdd.Connection = cn;

                                cmdSearch.CommandText = String.Format(CultureInfo.InvariantCulture,
                                                                      "Select IndexKey From IndexData Where GroupId = '{0}' And IndexKey = @key",
                                                                      groupId);
                                cmdSearch.Parameters.Add(new SqlParameter("@key", SqlDbType.VarChar, 768));

                                cmdAdd.CommandText = String.Format(CultureInfo.InvariantCulture,
                                                                   "IF NOT EXISTS(Select * From IndexData Where GroupId = '{0}' And IndexKey = @key) " +
                                                                   "Insert IndexData (GroupId, IndexKey, IndexValue) Values('{0}', @key, @value) " +
                                                                   "ELSE " +
                                                                   "Update IndexData Set IndexValue = @value Where GroupId = '{0}' And IndexKey = @key",
                                                                   groupId);

                                cmdAdd.Parameters.Add(new SqlParameter("@key", SqlDbType.VarChar, 768));
                                cmdAdd.Parameters.Add(new SqlParameter("@value", SqlDbType.Text));

                                // Get the keys from the file and add them to the index
                                foreach (var kv in base.GetValues(file))
                                {
                                    cmdSearch.Parameters[0].Value = cmdAdd.Parameters[0].Value = kv.Key;

                                    // Only report the warning if wanted
                                    if (cmdSearch.ExecuteScalar() != null && reportDuplicateIds)
                                    {
                                        this.Component.WriteMessage(MessageLevel.Warn, "An entry for the key '{0}' " +
                                                                    "already exists and will be replaced by the one from '{1}'", kv.Key, file);
                                    }

                                    cmdAdd.Parameters[1].Value = kv.Value.InnerXml;
                                    cmdAdd.ExecuteNonQuery();
                                }
                            }
                });
            }

            return(cache);
        }