Member 12983358 Ответов: 1

Вставка файла в mssql с помощью dapper


Есть ли способ вставить файл без использования параметров?
Я создаю строку, которая обновляет и вставляет данные в несколько таблиц одновременно, если что-то не удается, все изменения отклоняются.
Это мой код.:
if (Ordre.Attatchments.Where(x => x.SaveState == false).Count() > 0)
           {
               SqlSaveString.Append("INSERT INTO dbo.SaleAttatchments ([RefUid], [FilePath], [FileName], [FileType], [FileSize],[File], [AttatchInvoice]) VALUES");
               foreach (AttatchmentModel doc in Ordre.Attatchments.Where(x => x.SaveState == false).ToList())
               {
                   if (LineCount > 0) SqlSaveString.Append(",");
                   SqlSaveString.Append($"('{Ordre.SaleUid}', '{doc.FilePath}', '{doc.FileName}', '{doc.FileType}', {doc.FileSize}, {doc.File}, {doc.AttatchInvoice.BoolToTinyInt()})");
               }
               SqlSaveString.Append(";");
           }


Что я уже пробовал:

Этот код работает, но не то, что я ищу.
public void SaveFile(AttatchmentModel parameters, string connectionStringName)
        {
            string connectionString = GetConnectionString(connectionStringName);
            using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(connectionString))
            {
                var sql = "UPDATE dbo.SaleAttatchments SET[File] = @FileData WHERE RefUid = @Id And FileName = @FileName;";
                var dParams = new DynamicParameters();
                dParams.Add("@Id", parameters.RefUID, DbType.String);
                dParams.Add("@FileData", parameters.File, DbType.Binary);
                dParams.Add("@FileName", parameters.FileName, DbType.String);
                connection.Execute(sql, dParams);
            }
        }

Richard Deeming

"без использования параметров"

Почему? Вам нравится, что ваша база данных полностью уничтожена каждым случайным скриптом-детишкой на планете?!

НИКОГДА используйте конкатенацию строк / string.Format / интерполированные строки для построения SQL-запроса. ВСЕГДА используйте параметризованный запрос.

Все, что вы хотели знать о SQL-инъекции (но боялись спросить) | Трой Хант[^]
Как я могу объяснить SQL-инъекцию без технического жаргона? | Обмен Стеками Информационной Безопасности[^]
Шпаргалка по параметризации запросов | OWASP[^]

1 Ответов

Рейтинг:
0

Richard Deeming

Попробуй:

if (Ordre.Attatchments.Any(x => x.SaveState == false))
{
    string connectionString = GetConnectionString(connectionStringName);
    using (var connection = new System.Data.SqlClient.SqlConnection(connectionString))
    {
        const string sql = "UPDATE dbo.SaleAttatchments SET[File] = @FileData WHERE RefUid = @Id And FileName = @FileName;";
        
        var parameters = new List<DynamicParameters>();
        
        foreach (AttatchmentModel doc in Ordre.Attatchments.Where(x => x.SaveState == false))
        {
            var dParams = new DynamicParameters();
            dParams.Add("@Id", parameters.RefUID, DbType.String);
            dParams.Add("@FileData", parameters.File, DbType.Binary);
            dParams.Add("@FileName", parameters.FileName, DbType.String);
            parameters.Add(dParams);
        }
        
        connection.Execute(sql, parameters);
    }
}
Выполните команду несколько раз - Dapper[^]

В качестве альтернативы можно использовать транзакцию:
if (Ordre.Attatchments.Any(x => x.SaveState == false))
{
    string connectionString = GetConnectionString(connectionStringName);
    using (var connection = new System.Data.SqlClient.SqlConnection(connectionString))
    {
        const string sql = "UPDATE dbo.SaleAttatchments SET[File] = @FileData WHERE RefUid = @Id And FileName = @FileName;";
        
        connection.Open();
        
        using (var transaction = connection.BeginTransaction())
        {
            foreach (AttatchmentModel doc in Ordre.Attatchments.Where(x => x.SaveState == false))
            {
                var dParams = new DynamicParameters();
                dParams.Add("@Id", parameters.RefUID, DbType.String);
                dParams.Add("@FileData", parameters.File, DbType.Binary);
                dParams.Add("@FileName", parameters.FileName, DbType.String);
                connection.Execute(sql, parameters, transaction);
            }
            
            transaction.Commit();
        }
    }
}
В любом случае, НИКОГДА попробуйте встроить значения параметров непосредственно в SQL-запрос.


Member 12983358

Спасибо Ричард, я играл с тем решением, которое вы предложили, но так как я делаю так много различных обновлений/вставок, я попробовал что-то еще. Почему я никогда не должен вставлять свои параметры в sql?
Софар, это только то, что я сделал, остальное-процедуры. Но почему бы и нет?

Кстати, это локальное приложение с локальной базой данных, не предназначенное для WWW

Richard Deeming

Потому что вы сделаете свой код уязвимым для SQL-инъекция[^].

Не имеет значения, является ли это локальное приложение или веб-приложение. Пользователи локальных приложений все еще могут случайно вызвать проблемы, введя "неправильные" символы. И они все еще могут быть злонамеренными - не нужно много искать, чтобы найти истории о сотрудниках, наносящих преднамеренный ущерб сети своего работодателя непосредственно перед их уходом.

Кроме того, если вы используете параметры, вам никогда не придется беспокоиться о том, как отформатировать значения в подходящее строковое представление.