Нет эффекта от ApplicationIntent в строке подключения

271
05 августа 2017, 01:53

В приложении, работающем на EF 6.1.3 (Code-First), генерируются отчеты Excel. Заранее невозможно сказать какой отчет понадобится в конкретном случае и поэтому пользователю разрешено генерировать отчеты на основе своего SQL запроса. Каким образом можно ограничить SQL запросы только на чтение?

На данный момент создаю строку подключения с ApplicationIntent.ReadOnly, но никакого эффекта это не даёт:

IEnumerable<dynamic> ExecuteSqlQuery(string query) {
    string connStr = "...;ApplicationIntent=ReadOnly";
    using (SqlConnection conn = new SqlConnection(connStr)) {
        using (SqlCommand cmd = conn.CreateCommand()) {
            cmd.CommandText = query;
            if(cmd.Connection.State != ConnectionState.Open) {
                cmd.Connection.Open();
            }
            using (var dataReader = cmd.ExecuteReader()) {
                while (dataReader.Read()) {
                    var dataRow = GetDataRow(dataReader);
                    yield return dataRow;
                }
            }
        }
    }
}
// Remove record in DB
ExecuteSqlQuery("DELETE FROM [dbo].[Table] WHERE [dbo].[Col].[Id] = 1");

Может быть имеется другой способ добиться желаемого? Имеет ли смысл подставлять SELECT в начале запроса, а пользователю разрешить добавлять следующие за SELECT строки? Почему не работает ApplicationIntent?

Answer 1

Если тебе необходимо ограничить права пользователя, работающего с SQL-сервером, используй для этого механизмы SQL-сервера. Создай нового пользователя с ролями public и db_datareader. Он сможет только читать, и не сможет модифицировать записи.

Answer 2

У меня под рукой Oracle, поэтому покажу на ней, но для других БД код не будет отличаться:

static void Main(string[] args)
{
    var csb = new OracleConnectionStringBuilder
    {
        DataSource = "...",
        UserID = "...",
        Password = "..."
    };
    using (var connection = new OracleConnection(csb.ConnectionString))
    {
        connection.Open();
        var transaction = connection.BeginTransaction(); // Стартуем транзакцию
        var command = new OracleCommand("insert into ...", connection); // "Вредящая" команда
        command.Transaction = transaction; // Помещаем команду в созданную транзакцию
        using (var reader = command.ExecuteReader()) // Запускаем команду
        {
            ...
        }
        transaction.Rollback(); // Откатываем транзакцию
        // Если ее не закоммитить явно: transaction.Commit(),
        //  то она по умолчанию будет тоже откачена
    }
    Console.ReadLine();
}
READ ALSO
Как изменить props через ref в react js

Как изменить props через ref в react js

У меня есть родительский компонент и набор дочерних функциональных компонентов, refs на которые, я храню в массиве state родителяВ определенный...

356
Функция для js отправка текста

Функция для js отправка текста

есть функция которая обрабатывается через клик в textarea, как сделать такую же на на кнопку? {{STORY_ID}} - это id поста к которому привязан textarea , а {{PUBLISHER_ID}}...

324
Помогите написать алгоритм для Gulp

Помогите написать алгоритм для Gulp

ПриветЕсть алгоритм, который берёт все картинки(и сжимает их), все стили(минифицирует и объединяет в один) и скрипты - объединяет в один

292
Передача объектов в игре между классами

Передача объектов в игре между классами

Я пишу небольшую игру на JavaScript (ES6)Есть в игре объекты, такие как Camera, Scene и тд, к которым очень часто нужен доступ

267