Я использую Экспресс SQL Server 2005 года. Я хочу использовать SMO, чтобы циклично выполниться через каждую таблицу в базе данных и изменить каждый столбец Char на столбец Varchar. Если столбец является членом первичного ключа, я должен сначала отбросить первичный ключ прежде, чем изменить тип данных столбца. Затем я должен воссоздать индекс. Вот код, который я пытаюсь использовать:
foreach (Table table in database.Tables)
{
Index pk = table.Indexes.Cast<Index>().SingleOrDefault(index => index.IndexKeyType == IndexKeyType.DriPrimaryKey);
if (pk != null)
{
pk.Drop();
table.Alter();
}
foreach (Column column in table.Columns.Cast<Column>().Where(column => column.DataType.SqlDataType == SqlDataType.Char))
{
column.DataType = new DataType(SqlDataType.VarChar, column.DataType.MaximumLength);
}
table.Alter();
if (pk != null)
{
pk.Create();
}
}
Но когда я пытаюсь создать индекс, я добираюсь, исключение с сообщением "Не может получить доступ к свойствам или методам для Microsoft. SqlServer. Управление. Smo. Индекс ' [PK_table1] ', потому что это было отброшено". Так есть ли хороший способ выполнить то, что я хочу сделать с SMO?
Я пытался писать сценарий индекса, прежде чем я отбросил его с помощью метода Сценария Индекса, но он выдает исключение с сообщением "Индексные 'PK_table1' ссылки несуществующий столбец' [table1]. [владелец]'". Столбец владельца ясно существует.
Возможно, объект индекса потерял ссылку на таблицу. Вы пытались добавить индекс обратно к объекту таблицы?
table.Indexes.Add(pk);
Попробуйте еще раз создать первичный ключ следующим образом.
Index index = new Index(table, "PK_tableNameTable");
index.IndexKeyType = IndexKeyType.DriPrimaryKey;
//You will have to store the names of columns before deleting the key.
index.IndexedColumns.Add(new IndexedColumn(index,"ID"));
table.Indexes.Add(index);
Есть ли у вас возможность запускать сценарии SQL через SMO? Я начал запускать все скрипты, которые вносят какие-либо структурные изменения в БД, через ServerConnection.ExecuteNonQuery. Большое улучшение стабильности по сравнению с обычным стеком SqlCommand и т. Д. (Тоже не идет вразрез с GO :-) В итоге получилось очень полезное слияние. Разумеется, не-MARS соединение.
Вместо того чтобы удалять и воссоздавать индекс, попробуйте просто отключить его, а затем снова включить, когда закончите, используя методы .Disable
и .Enable
.
Мне удалось удалить первичный ключ, изменить типы данных столбца и воссоздать первичный ключ с помощью этого кода:
// using System.Collections.Specialized;
foreach (Table table in database.Tables)
{
// object to hold the index script
StringCollection pk_script = new StringCollection();
Index pk = table.Indexes.Cast<Index>().SingleOrDefault(index => index.IndexKeyType == IndexKeyType.DriPrimaryKey);
if (pk != null)
{
// script the index
pk_script = pk.Script();
pk.Drop();
table.Alter();
}
foreach (Column column in table.Columns.Cast<Column>().Where(column => column.DataType.SqlDataType == SqlDataType.Char))
{
column.DataType = new DataType(SqlDataType.VarChar, column.DataType.MaximumLength);
}
table.Alter();
// iterate through script StringCollection
foreach (String tsql in pk_script)
{
database.ExecuteNonQuery(tsql);
}
}
Некоторые предостережения: