public void EqualsTest()
        {
            // Arrange.
            var index1 = new DbIndexDefinition
                             {
                                 Name = "TestIndex",
                                 TableName = "TestTable",
                                 IsUnique = false,
                                 Columns = { new DbIndexColumnDefinition { Name = "TestColumn", SortOrder = DbSortOrder.Ascending } }
                             };

            var index2 = new DbIndexDefinition
                             {
                                 Name = "TestIndex",
                                 TableName = "TestTable",
                                 IsUnique = false,
                                 Columns = { new DbIndexColumnDefinition { Name = "TestColumn", SortOrder = DbSortOrder.Ascending } }
                             };

            var index3 = new DbIndexDefinition
                             {
                                 Name = "TestIndexNew",
                                 TableName = "TestTable",
                                 IsUnique = false,
                                 Columns = { new DbIndexColumnDefinition { Name = "TestColumn", SortOrder = DbSortOrder.Ascending } }
                             };

            var index4 = new DbIndexDefinition
                             {
                                 Name = "TestIndex",
                                 TableName = "TestTableNew",
                                 IsUnique = false,
                                 Columns = { new DbIndexColumnDefinition { Name = "TestColumn", SortOrder = DbSortOrder.Ascending } }
                             };

            var index5 = new DbIndexDefinition
                             {
                                 Name = "TestIndex",
                                 TableName = "TestTable",
                                 IsUnique = true,
                                 Columns = { new DbIndexColumnDefinition { Name = "TestColumn", SortOrder = DbSortOrder.Ascending } }
                             };

            var index6 = new DbIndexDefinition
                             {
                                 Name = "TestIndex",
                                 TableName = "TestTable",
                                 IsUnique = false,
                                 Columns = { new DbIndexColumnDefinition { Name = "TestColumnNew", SortOrder = DbSortOrder.Ascending } }
                             };

            // Act / Assert.
            Assert.IsFalse(index1.Equals(null as object));
            Assert.IsTrue(index1.Equals(index2 as object));
            Assert.IsFalse(index1.Equals(index3 as object));
            Assert.IsFalse(index1.Equals(index4 as object));
            Assert.IsFalse(index1.Equals(index5 as object));
            Assert.IsFalse(index1.Equals(index6 as object));
        }
        /// <summary>
        /// Gets the system index definitions for all processes in the runtime database.
        /// </summary>
        /// <returns>
        /// The collection of index definitions.
        /// </returns>
        private IEnumerable<DbIndexDefinition> GetExistingSystemIndexes()
        {
            const string CommandText = @"
DECLARE @Indexes TABLE
(
     object_id      INT
    ,index_id       INT
    ,[TableName]    NVARCHAR(128)
    ,[IndexName]    NVARCHAR(128)
    ,[IsUnique]     BIT
)

INSERT INTO @Indexes
    SELECT
         i.object_id
        ,i.index_id
        ,t.name AS [TableName]
        ,i.name AS [IndexName]
        ,i.is_unique AS [IsUnique]
    FROM
        sys.indexes i
        INNER JOIN sys.tables t ON i.object_id = t.object_id
        INNER JOIN sys.schemas s ON s.schema_id = t.schema_id
    WHERE s.name = 'dbo' AND i.name LIKE 'SystemIndex-%'

SELECT
     [TableName]
    ,[IndexName]
    ,[IsUnique]
FROM
    @Indexes

SELECT
     i.[TableName]
    ,i.[IndexName]
    ,c.name AS [ColumnName]
    ,ic.is_descending_key AS [IsDescending]
FROM
    sys.index_columns ic
    INNER JOIN @Indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
    INNER JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
ORDER BY i.[TableName], i.[IndexName], ic.key_ordinal";

            using (var ctx = GetRuntimeDatabaseConnectionManager())
            {
                using (var cmd = new SqlCommand(CommandText, ctx.Connection))
                {
                    using (var reader = cmd.ExecuteReader())
                    {
                        var indexes = new List<DbIndexDefinition>();

                        while (reader.Read())
                        {
                            var index = new DbIndexDefinition
                                            {
                                                TableName = reader.GetString("TableName"),
                                                Name = reader.GetString("IndexName"),
                                                IsUnique = reader.GetBoolean("IsUnique")
                                            };

                            indexes.Add(index);
                        }

                        reader.NextResult();

                        DbIndexDefinition currentIndex = null;

                        while (reader.Read())
                        {
                            var tableName = reader.GetString("TableName");
                            var indexName = reader.GetString("IndexName");

                            if (currentIndex == null || currentIndex.TableName != tableName || currentIndex.Name != indexName)
                            {
                                currentIndex = indexes.First(i => i.TableName == tableName && i.Name == indexName);
                            }

                            currentIndex.Columns.Add(
                                new DbIndexColumnDefinition
                                    {
                                        Name = reader.GetString("ColumnName"),
                                        SortOrder = reader.GetBoolean("IsDescending") ? DbSortOrder.Descending : DbSortOrder.Ascending
                                    });
                        }

                        return indexes;
                    }
                }
            }
        }
        /// <summary>
        /// Drops the specified index.
        /// </summary>
        /// <param name="index">
        /// The index.
        /// </param>
        private void TryDropIndex(DbIndexDefinition index)
        {
            try
            {
                var commandText = string.Format(CultureInfo.InvariantCulture, "DROP INDEX [{0}] ON [dbo].[{1}]", index.Name, index.TableName);

                using (var ctx = GetRuntimeDatabaseConnectionManager())
                {
                    using (var cmd = new SqlCommand(commandText, ctx.Connection))
                    {
                        cmd.ExecuteNonQuery();
                    }
                }
            }
            catch (SqlException ex)
            {
                Logger.Log(LogSeverity.Error, "SqlServerDatabaseGenerator", ex);
            }
        }
        /// <summary>
        /// Creates the specified index in the runtime database.
        /// </summary>
        /// <param name="indexDefinition">
        /// The index definition.
        /// </param>
        private void TryCreateIndex(DbIndexDefinition indexDefinition)
        {
            try
            {
                var indexType = indexDefinition.IsUnique ? "UNIQUE" : "NONCLUSTERED";
                var indexColumnSelectStatements = indexDefinition.Columns.Select(c => string.Format("    SELECT '{0}' AS [ColumnName]", c.Name));
                var indexColumnSelectSeparator = Environment.NewLine + string.Format("    UNION") + Environment.NewLine;
                var commandText = new StringBuilder();
                commandText.AppendFormat(
                    @"
DECLARE @totalBytes INT;

WITH IndexColumns
AS
(
{4}
)
SELECT @totalBytes = SUM(c.max_length)
FROM
    sys.columns c
    INNER JOIN sys.tables t ON t.object_id = c.object_id
    INNER JOIN sys.schemas s ON s.schema_id = t.schema_id
    INNER JOIN IndexColumns ic ON ic.[ColumnName] = c.name
WHERE t.name = '{2}' AND s.name = 'dbo'

IF ((@totalBytes IS NULL) OR (@totalBytes <= 900))
    BEGIN
        CREATE {0} INDEX [{1}] ON [dbo].[{2}] ({3}) WHERE [IsRemoved] = 0
    END
ELSE
    BEGIN
        RAISERROR(N'Cannot create the index ''{1}'' because the index key size is greater than 900 bytes.', 16, 0)
    END
",
                    indexType,
                    indexDefinition.Name,
                    indexDefinition.TableName,
                    string.Join(", ", indexDefinition.Columns.Select(FormatIndexColumn)),
                    string.Join(indexColumnSelectSeparator, indexColumnSelectStatements));

                using (var ctx = GetRuntimeDatabaseConnectionManager())
                {
                    using (var cmd = new SqlCommand(commandText.ToString(), ctx.Connection))
                    {
                        cmd.ExecuteNonQuery();
                    }
                }
            }
            catch (SqlException ex)
            {
                Logger.Log(LogSeverity.Error, "SqlServerDatabaseGenerator", ex);
            }
        }
 /// <summary>
 /// Determines whether the specified index is equivalent to the clustered index.
 /// </summary>
 /// <param name="index">
 /// The index definition.
 /// </param>
 /// <returns>
 /// <c>true</c> if the specified index is equivalent to the clustered index; otherwise, <c>false</c>.
 /// </returns>
 private static bool IsEquivalentToClusteredIndex(DbIndexDefinition index)
 {
     return index.Columns.Count == 1 && index.Columns[0].Name == Constants.IdColumnName;
 }
 /// <summary>
 /// Determines whether the specified index is reduntant, i.e. there is an equivalent index on the same table.
 /// </summary>
 /// <param name="index">
 /// The index definition.
 /// </param>
 /// <returns>
 /// <c>true</c> if the specified index is redundant; otherwise, <c>false</c>.
 /// </returns>
 private static bool IsReduntant(DbIndexDefinition index)
 {
     return IsEquivalentToClusteredIndex(index);
 }
        /// <summary>
        /// Gets the definitions of the system indexes that should be created for the processes in the specified libraries.
        /// </summary>
        /// <param name="libraryTypes">
        /// The library types.
        /// </param>
        /// <returns>
        /// The collection of index definitions.
        /// </returns>
        private static IEnumerable<DbIndexDefinition> GetProcessIndexDefinitions(LibraryTypes libraryTypes)
        {
            const string CommandText = @"
DECLARE @Indexes TABLE
(
     [Id]           INT
    ,[ProcessName]  NVARCHAR(200)
    ,[IsUnique]     BIT
);

INSERT INTO @Indexes
    SELECT
         i.[Id]
        ,p.[SystemName]
        ,i.[IsUnique]
    FROM
        [dbo].[ProcessIndexes] i
        INNER JOIN [dbo].[Processes] p ON p.[Id] = i.[ProcessId]
    WHERE p.[IsRemoved] = 0 AND p.[IsInactive] = 0 AND (
        (p.[IsSystem] = 1 AND @includeSystemProcesses = 1) OR (p.[IsSystem] = 0 AND @includeCustomProcesses = 1))

SELECT *
FROM
    @Indexes

SELECT
     f.[IndexId]
    ,f.[FieldName]
    ,f.[SortOrder]
FROM
    [dbo].[ProcessIndexFields] f
    INNER JOIN @Indexes i ON i.[Id] = f.[IndexId]
ORDER BY f.[IndexId], f.[FieldOrdinal]";

            using (var ctx = GetMetaDatabaseConnectionManager())
            {
                using (var cmd = new SqlCommand(CommandText, ctx.Connection))
                {
                    cmd.Parameters.AddWithValue("@includeSystemProcesses", libraryTypes.HasFlag(LibraryTypes.System));
                    cmd.Parameters.AddWithValue("@includeCustomProcesses", libraryTypes.HasFlag(LibraryTypes.Custom));

                    using (var reader = cmd.ExecuteReader())
                    {
                        var indexList = new List<DbIndexDefinition>();
                        var indexMap = new Dictionary<int, DbIndexDefinition>();

                        while (reader.Read())
                        {
                            var indexId = reader.GetInt32("Id");
                            var indexName = string.Format("SystemIndex-{0}", indexId);
                            var index = new DbIndexDefinition
                            {
                                Name = indexName,
                                TableName = reader.GetString("ProcessName"),
                                IsUnique = reader.GetBoolean("IsUnique")
                            };

                            indexList.Add(index);
                            indexMap.Add(indexId, index);
                        }

                        reader.NextResult();

                        while (reader.Read())
                        {
                            var indexId = reader.GetInt32("IndexId");
                            var index = indexMap[indexId];
                            index.Columns.Add(
                                new DbIndexColumnDefinition
                                {
                                    Name = reader.GetString("FieldName"),
                                    SortOrder = reader.GetEnum("SortOrder", DbSortOrder.Unspecified)
                                });
                        }

                        return indexList;
                    }
                }
            }
        }
        public void GetHashCodeTest()
        {
            // Arrange.
            var index1 = new DbIndexDefinition
                             {
                                 Name = "TestIndex",
                                 TableName = "TestTable",
                                 IsUnique = false,
                                 Columns = { new DbIndexColumnDefinition { Name = "TestColumn", SortOrder = DbSortOrder.Ascending } }
                             };

            var index2 = new DbIndexDefinition
                             {
                                 Name = "TestIndex",
                                 TableName = "TestTable",
                                 IsUnique = false,
                                 Columns = { new DbIndexColumnDefinition { Name = "TestColumn", SortOrder = DbSortOrder.Ascending } }
                             };

            // Act / Assert.
            Assert.AreEqual(index1.GetHashCode(), index2.GetHashCode());
        }