Можно ли экспортировать результат строк, отредактированных в SqlString?
У меня есть установщик, который устанавливает базу данных. База данных создается вместе с некоторыми логинами. Для создания логинов я использую базу данных master в элементах SqlString. Доступ к основной базе данных предоставляется только пользователям, которые имеют очень высокие права на сервере SQL. Часто установка прерывается, потому что строка SQL, предназначенная для базы данных master, не может быть выполнена из-за отсутствия прав.
Я хочу отредактировать мой установщик, чтобы при невозможности выполнения элемента SqlString часть установки SQL пропускалась. После установки я хочу, чтобы пользователь мог сам выполнять операторы SQL. Каждое действие SQL, выполняемое моим установщиком, хранится в элементах SqlString. Элементы SqlString содержат множество свойств, которые заменяются во время установки. Я хочу извлечь содержимое всех отредактированных элементов SqlString в один файл sql, хранящийся в каталоге пользователя.
Я предполагаю, что мне придется написать ограничение, которое имеет место после того, как sqlextension заменило свойства. И тогда мне придется получить доступ к этим измененным строкам. Есть ли способ, которым я могу сделать это?
Пример элемента SqlString:
<sql:SqlDatabase Id="MasterDB" Server="[SQLSERVER_SERVER]" Instance="[SQLSERVER_INSTANCENAME]" Database="master" />
<sql:SqlString
SqlDb="MasterDB"
Id="CreateNetworkServiceAccount"
ExecuteOnInstall="yes"
ContinueOnError="no"
SQL="IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'{[WIX_ACCOUNT_NETWORKSERVICE]}')
CREATE LOGIN [\[]{[WIX_ACCOUNT_NETWORKSERVICE]}[\]] FROM WINDOWS WITH DEFAULT_DATABASE=[\[]master[\]]"
Sequence="101"/>
Пример файла sql, который я хотел бы получить после сбоя SqlStrings:
USE master;
IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'NT AUTHORITY\Network Service')
CREATE LOGIN [NT AUTHORITY\Network Service] FROM WINDOWS WITH DEFAULT_DATABASE=[master]
1 ответ
Я решил эту проблему с довольно странным решением. Я написал CustomAction, который извлекает элементы String из таблицы SqlString, а затем заменяет отформатированные поля соответствующими свойствами, хранящимися в сеансе. Чтобы иметь доступ к переменной сеанса, CustomAction должен быть выполнен как immediate
, Я запланировал это раньше InstallFinalize
получить доступ к PersonalFolder
имущество. С помощью этого свойства я могу сохранить сценарий Sql, сгенерированный записями в таблице SqlScript, в пользовательском каталоге Documents. Чтобы учесть разные базы данных при установке, я включил поиск в таблицу SqlDatabase.
Вот код для CustomAction:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Deployment.WindowsInstaller;
using System.IO;
using System.Text.RegularExpressions;
namespace SaveSqlStrings
{
public class CustomActions
{
[CustomAction]
public static ActionResult SaveSqlStrings(Session session)
{
StringBuilder sqlStrings = new StringBuilder();
Database db = session.Database;
View view = db.OpenView("SELECT * FROM `SqlString`");
IList<string> SqlStringElements = db.ExecuteStringQuery("SELECT `String` FROM `SqlString`");
Regex bracketedProperties = new Regex(@"\[(\b[A-Z_]*\b)\]");
Regex formattedProperties = new Regex(@"{\[(\b[A-Z_]*\b)\]}");
Regex openeningSquareBrackets = new Regex(@"\[\\\[\]");
Regex closingSquareBrackets = new Regex(@"\[\\\]\]");
string sqlDb_ = "";
string sqlString = "";
string Database = "";
foreach (string dbString in SqlStringElements)
{
sqlDb_ = (string)db.ExecuteScalar("SELECT `SqlDb_` FROM `SqlString` WHERE `String` ='{0}'",dbString);
sqlString = (string)db.ExecuteScalar("SELECT `SQL` FROM `SqlString` WHERE `String` ='{0}'",dbString);
view.Close();
view = db.OpenView("SELECT * FROM `SqlDatabase`");
Database = (string)db.ExecuteScalar("SELECT `Database` from `SqlDatabase` WHERE `SqlDb`='{0}'", sqlDb_);
if(bracketedProperties.IsMatch(Database))
{
Database = bracketedProperties.Match(Database).Groups[1].Value;
Database = session[Database];
}
if (openeningSquareBrackets.IsMatch(sqlString))
sqlString = openeningSquareBrackets.Replace(sqlString, "[");
if (closingSquareBrackets.IsMatch(sqlString))
sqlString = closingSquareBrackets.Replace(sqlString, "]");
if(formattedProperties.IsMatch(sqlString))
{
string propertyName = formattedProperties.Match(sqlString).Groups[1].Value;
string propertyValue = session[propertyName];
sqlString = formattedProperties.Replace(sqlString, propertyValue);
}
sqlStrings.AppendLine(String.Format("use {0}",Database));
sqlStrings.AppendLine(sqlString);
}
string home = session["PersonalFolder"];
string sqlPath = string.Concat(home, @"Script.sql");
try
{
File.WriteAllText(sqlPath, sqlStrings.ToString());
}
catch (Exception ex)
{
session["FailedTowrite"] = sqlPath;
}
view.Close();
db.Close();
return ActionResult.Success;
}
}
}