2010-11-18 2 views
2

Работа с MYSQL в C#:Дозирование вместе параметризованные команды в MYSQL

У меня есть коллекция параметризованных IDbCommands Я хотел бы выполнить. Представляют собой смесь обновлений, вставок и удалений, прямо сейчас я делаю:


using (IDbConnection connection = Connecter.CreateConnection()) 
{ 
    foreach(IDBCommand command in m_commands) 
    { 
    command.Connection = connection; 
    command.ExecuteNonQuery(); 
    } 
} 

Команда интенсивно используют параметры, так что я не могу просто объединить командные тексты каждой команды вместе. Производительность довольно ужасная, и я знаю, что должен быть лучший способ.

Использование массового обновления MYSql было бы приемлемым, но мне не ясно, как преобразовать значения параметров в файл, не рискуя атаками SQL-инъекций.

У кого-нибудь есть предложения?

(я привязал положить все команды внутри транзакции, которая помогает некоторым, но не достаточно)

ответ

1

Если несколько вставки/обновления/удалений должны быть применены к одной и той же таблицы (ы), рассмотрите возможность использования комбинации MySqlDataAdapter/DataTable для пакетной работы как заявления. Установка свойства UpdateBatchSize MySqlDataAdapter позволит включить/отключить поддержку пакетной обработки. Таким образом, вставки/обновления/удаления в одной и той же таблице могут быть отправлены в БД за одну поездку.

Я сделал это с OracleDataAdapter и SqlDataAdapter со значительным приростом производительности. MySqlDataAdapter также реализует базовую доработку (хотя на самом деле не тестировал ее).

Одним из предложений было бы создать собственный класс-оболочку, который скрывает классы DbDataAdapter/DataTable в какой-то форме класса DbCommandBatch. Затем этот класс может создать необходимую поддержку DataTable из шаблона IDbCommand и, в случае необходимости, группироваться вместе, например, команды.

public interface IDbBatchCommandFactory 
{ 
    IDbCommandBatch Create(IDbCommand templateCommand); 
} 

Так Создать метод действительно может построить до требуемого DataTable из команды шаблона при желании (может облегчить жизнь в зависимости от того, какой код у вас уже есть) перебором существующей коллекции параметров. Это может затем создать класс, который реализует интерфейс что-то вроде:

public interface IDbBatchCommand : IDisposable 
{ 
    void AddToBatch(ParameterCollection parameters); 
    void ExecuteBatch(IDbTransaction transaction); 
} 

Если это на правильном пути для того, что вам нужно, я могу предоставить образец кода. Если каждая команда отличается друг от друга (т. Е. Всегда разные таблицы и т. Д.), То это не даст никакого значения.

Примечание: В идеальном мире такие классы, как SqlCommandSet и т. Д., Будут доступны для публики, чтобы избежать необходимости делать это беззаботно.

+0

Спасибо, с помощью DataTable был путь. –

0

у меня нет большого опыта работы с использованием MySQL, так что я не знаком с функциональностью массовых обновлений, что это есть. Это звучит многообещающе для того, что вы хотели бы сделать, но я вижу вашу обеспокоенность, если вам необходимо сначала сохранить данные в виде файла, прежде чем использовать Bulk Update.

Я не уверен, что MySQL имеет что-то похожее на это, но ADO.NET provides a SqlBulkCopy command, который работает с SQL Server. Это в основном позволяет вставлять данные в базу данных непосредственно из считывателя данных, предоставляемого вашим кодом, минуя необходимость создания файла и, следовательно, избегая необходимости беспокоиться о связанных с строкой проблемах.

MySQL 4.1 has prepared statements. Являются ли эти команды одинаковыми, за исключением значений параметров? Я интересно, если бы вы увидеть более высокую производительность, если вы пытались воспользоваться методом IDbCommand.Prepare:

 using (IDbConnection connection = Connector.CreateConnection()) 
     { 
      var command = connection.CreateCommand(); 

      command.CommandText = "<command text>"; 

      var paramA = command.CreateParameter(); 
      paramA.ParameterName = "ParameterA"; 
      paramA.DbType = DbType.Int32; 
      command.Parameters.Add(paramA); 

      var paramB = command.CreateParameter(); 
      paramB.ParameterName = "ParameterB"; 
      paramB.DbType = DbType.String; 
      command.Parameters.Add(paramB); 

      var paramC = command.CreateParameter(); 
      paramC.ParameterName = "ParameterC"; 
      paramC.DbType = DbType.Decimal; 
      command.Parameters.Add(paramC); 

      command.Prepare(); 

      foreach (ProcedureArgs args in m_procedureArgs) 
      { 
       paramA.Value = args.ParamA; 
       paramB.Value = args.ParamB; 
       paramC.Value = args.ParamC; 
       command.ExecuteNonQuery(); 
      } 
     } 
Смежные вопросы