SQL + Informix: как добавить BLOB-объект при вставке?(Использование .NET (C #) SDK) - PullRequest
2 голосов
/ 07 июня 2011

Я использую Informix и .NET SDK (C #):

В принципе, есть ли способ вставить BLOB-объект при выполнении стандартного оператора вставки SQL?

INSERT INTO mytable (name, theblob) VALUES ('foo', ? what goes here ?);

Да, и данные, которые у меня есть, представлены в виде массива byte [].

Ответы [ 4 ]

1 голос
/ 20 июня 2011

Пара заметок:

1) Вы должны использовать параметризованные запросы

//Assuming you already have a connection somewhere that is opened.

var sql = "INSERT INTO mytable (name, theblob) VALUES (?, ?);";

using (var command = new IfxCommand(sql, connection))
{
    command.Parameters.Add(new IfxParameter()).Value = "foo";
    command.Parameters.Add(new IfxParameter()).Value = ifxBlob;
}


Несколько вещей, на которые следует обратить внимание: Informix имеет ошибку, когда дело доходит до Client SDK 3.5.xC7 (пока). Вы можете легко передать байтовый массив во время вставок, но при обновлении у вас будет ошибка 609, если вы передадите массив byte []. Вместо этого вы должны использовать объект IfxBlob.
public IfxBlob CreateIfxBlob(byte[] data)
{
    //Get the connection however you like and make sure it's open...
    //Obviously you should make this method handle exceptions and the such.

    IfxBlob blob = connection.GetIfxBlob();

    blob.Open(IfxSmartLOBOpenMode.ReadWrite);
    blob.Write(data);
    blob.Close();

    return blob;
}

Вы должны передать IfxBlob вместо этого во время обновления, так что вы могли бы также сделать это во время вставок.

Также имейте в виду, что если вы попытаетесь установить null, вы получите ошибку. Вместо этого, если значение равно нулю, передайте DBNull.Value.

public Object AsDBValue(Object value) //Or this Object value if you want it as an extension
{
    if (value == null)
        return DBNull.Value;

    //Other checks
    if (value is Enum)
        return Convert.ChangeType(value, value.GetType().GetEnumUnderlyingType());

    //Is Blob?
    if (value is byte[])
        return GetIfxBlob(value as byte[]);

    return value;
}

НЕ УКАЗАТЬ ТИП ПАРАМЕТРА

//These will lead to errors unless you typecast the parameters in the query.
new IfxParameter { IfxType = IfxType.Blob };
new IfxParameter { DbType = DbType.Binary };

Если вы выполните одно из этих действий, вам нужно будет сделать следующее:

  • Когда значение Blob не равно нулю : "INSERT INTO mytable (name, theblob) VALUES (?, ?::blob);";
  • Когда значение BLOB-объекта равно нулю : "INSERT INTO mytable (name, theblob) VALUES (?, ?::byte);";

Вы можете видеть, что в заднице будет сложно иметь разные запросы из-за типа и значения. Просто не указывайте DbType или IfxType и позволяйте провайдеру Informix .NET отображать правильные типы для вас (даже если он не может правильно отобразить массив byte [] при обновлении).

Надеюсь, у вас это получится, потому что я прошел через те же усилия, пытаясь выяснить это и обнаружив, как мне кажется, ошибку в поставщике Informix .NET (версия: 3.5.xC7).

1 голос
/ 07 июня 2011

Лучше всего использовать параметризованный запрос.Например:

using(System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand("INSERT INTO mytable (name, theblob) VALUES ('foo', @binaryValue)", conn))
{
  cmd.Parameters.Add("@binaryValue", System.Data.SqlDbType.Text, 8000).Value = arraytoinsert;
  cmd.ExecuteNonQuery();
}

Я сделал предположение, что ваш тип столбца Text.Оригинальный кредит для вышеупомянутого подхода от этого сообщения .

0 голосов
/ 31 мая 2012

это сообщение было действительно полезно для решения моих проблем, поэтому я хотел бы поделиться своим решением, оно может помочь другимВот полный код:

        try
        {
            //pFoto is a byte[] loaded in another method.
            if (pFoto != null && pFoto.Length > 0)
            {
                StringBuilder sentenciaSQL = new StringBuilder();
                sentenciaSQL.Append("INSERT INTO bd_imagenes:imagenes ");
                sentenciaSQL.Append("(identificador, cod_imagen, fecha_desde, fecha_hasta, fecha_grabacion, usuario, sec_transaccion, imagen) ");
                sentenciaSQL.Append("VALUES (?, 'FP', current, null, current, ?, 0, ?);");

                using (IfxConnection conIFX = new IfxConnection("Database=bd_imagenes; Server=xxxxxxxx; uid=xxxxxxx; password=xxxxxxxx; Enlist=true; Client_Locale=en_US.CP1252;Db_Locale=en_US.819"))
                {
                    conIFX.Open(); //<- Abro la conexion.
                    //Aqui convierto la foto en un BLOB:                        
                    IfxBlob blob = conIFX.GetIfxBlob();
                    blob.Open(IfxSmartLOBOpenMode.ReadWrite);
                    blob.Write(pFoto);
                    blob.Close(); 

                    //Creo el Comando con la SQL:
                    using (IfxCommand cmd = new IfxCommand(sentenciaSQL.ToString(), conIFX))
                    {
                        //Agrego los parámetros en el mismo orden que la SQL:
                        cmd.Parameters.Add(new IfxParameter()).Value = pCedula;
                        cmd.Parameters.Add(new IfxParameter()).Value = SecurityHandler.Auditoria.NombreUsuario;
                        cmd.Parameters.Add(new IfxParameter()).Value = blob;
                        //Ejecuto la Consulta:
                        Resultado = cmd.ExecuteNonQuery();
                    }
                    conIFX.Close();  
                }
                if (Resultado != 0) { retorno = true; }
            }
        }
        catch (IfxException ae)
        {
            if (exepcionesValidacion == null) { exepcionesValidacion = new ArrayList(); }
            exepcionesValidacion.Add(Util.CrearExcepcion(ae.Message, "ERROR_INESPERADO", ae.StackTrace));
        }
        catch (Exception ex)
        {
            if (exepcionesValidacion == null) { exepcionesValidacion = new ArrayList(); }
            exepcionesValidacion.Add(Util.CrearExcepcion(ex.Message, "ERROR_INESPERADO", ex.StackTrace));
        }
        return retorno;
    }
0 голосов
/ 21 ноября 2011

Я прочитал оба ваших сообщения, и это решение мне помогло:

 byte[] data = File.ReadAllBytes(PathFile);

 StringBuilder sql = new StringBuilder();

sql.Append(" UPDATE  updater SET report = ?  where path = " + "\'" + Path + "\' and status = 1;");
IfxCommand cmd = new IfxCommand(sql.ToString(), i_connect);
cmd.Parameters.Add("@binaryValue", IfxType.Byte).Value = data;
int res = cmd.ExecuteNonQuery();

PathFile - это файл.txt

моя таблица Informix:

   CREATE TABLE updater
 (
    nzp_up SERIAL PRIMARY KEY,
    version VARCHAR(50),
    status INT,
    path VARCHAR(200),
    key VARCHAR(100),
    soup VARCHAR(20),
    report TEXT
 );
...