-14

私のWebサービスのサブタスクは、ファイルを(いくつかのメタデータとともに)データベースに保存することです。Webサービスは、 ServiceStackとそのバージョンのORMlite
に 基づいています。 そこで、データベース内の添付ファイルを表す小さなクラスを作成しました。

public class Attachment {
    public string Description { get; set; }
    public string FileName { get; set; }
    public string Type { get; set; }
    public byte[] Data { get; set; }
}

そしてここに実際のファイルがあります

MemoryStream ms = new MemoryStream(webclient.DownloadData(...));
byte[] data = new byte[...];
ms.Read(data, 0, data.Length);

Attachment file = new Attachment() {
    /* all the other stuff */
    Data = data
};

今まで問題ありません...:)

これで、このファイルをデータベースに入れるために必要なものがすべて揃いました。だからそれを乗せましょう...

dbCmd.Insert<Attachment>(file);


そして問題があります...

SqlException: "Operand type clash: text is incompatible with image"


ORMliteは、バイト配列をbase64でエンコードされた文字列に変換します

/* stripped-down example of the command string */
INSERT INTO Attachment (Data) VALUES ('CgoKCgoKCjxodG1sPgo8a...AAAA==')


私は一日中検索しましたが、ORMliteがbyte[]配列を処理する方法を変更するための解決策を見つけられませんでした。Javaで可能なのでDatabaseField、に設定するために使用できるdataType属性はありません。BYTE_ARRAY

@DatabaseField(dataType = DataType.BYTE_ARRAY)
byte[] imageBytes;


私は何か重要なものを見逃したことがありますか?
ファイルをデータベースに取り込む別の方法はありますか?

4

3 に答える 3

5

したがって、ServiceStack内のORMLiteとJava ORMライブラリのORMLiteの間で混乱していると思います。これらは関連しておらず、互換性も必要ありません。

あなたが尋ねているかもしれないのは、C#ORMLiteを使用してJavaORMLiteによって書き込まれたデータを読み取る方法です。私はC#側の経験はまったくありませんが、ORMLiteがここで何をしているのかについて話すことができます。

@DatabaseField(dataType = DataType.BYTE_ARRAY)
byte[] imageBytes;

SqlServerでは、これは次のフィールドに対応している必要があります。

"bytes" IMAGE

JDBCに渡されるSQL挿入コマンドは次のとおりです。

 INSERT INTO "bytearray" ("bytes" ) VALUES (?)
 insert arguments: [[B@34883357] (byte[])

byte[]を使用して結果からを取得しますresults.getBytes(columnPos)

あなたが言及する:

ORMliteは、バイト配列をbase64でエンコードされた文字列に変換します

これは、これを行うJDBCです。驚いていますが、可能だと思います。

ここに何かが役立つことを願っています。

于 2012-07-19T16:03:07.880 に答える
0

ServiceStack.OrmLite v4では、コメントのmythzで指定されているように、すべてがそのまま機能するはずです。


v3では、バイト配列をbase 64文字列ではなくバイナリとしてシリアル化する場合は、SqliteOrmLiteDialectProviderバイト配列を処理するために、SQL値との間でCLR値を変換する関数を継承およびオーバーライドする必要があります。

public class ByteArrayAwareSqliteOrmLiteDialectProvider
    : SqliteOrmLiteDialectProvider {

    public override object ConvertDbValue(object value, Type type) {
        var bytes = value as byte[];
        if (bytes != null && type == typeof(byte[]))
            return bytes;

        return base.ConvertDbValue(value, type);
    }

    public override string GetQuotedValue(object value, Type fieldType) {
        var bytes = value as byte[];
        if (bytes != null && fieldType == typeof(byte[]))
            return "X'" + BitConverter.ToString(data).Replace("-", "") + "'";

        return base.GetQuotedValue(value, fieldType);
    }

}

次に、方言プロバイダーを適切に構成します。

OrmLiteConfig.DialectProvider = new ByteArrayAwareSqliteOrmLiteDialectProvider();
于 2014-02-17T21:55:38.013 に答える
0

Oracleプロバイダーの場合、プロジェクトがUDT作業を行っていたため、ODP.NETライブラリ(Oracle.DataAcess)を使用する必要があり、OracleParameterオブジェクトにUDTTypeオブジェクトが必要だったため、Oracleプロバイダーの3.9.71をフォークしました。また、圧縮された独自の「xmllike」文字列をバイト配列としてBLOB列に挿入していました。

私のプロジェクトでは、

public class OracleOrmLiteDialectProvider : OrmLiteDialectProviderBase<OracleOrmLiteDialectProvider>
... 
    public override string GetQuotedValue(object value, Type fieldType)
    {
... 
        if (fieldType == typeof(byte[]))
        {
            var bytes = value as byte[];
            return "to_blob (utl_raw.cast_to_raw('" + Encoding.UTF8.GetString(bytes)+ "'))";
        }
...
}

もちろん、より良い解決策は、来年の予算で計画を立てて4.0に移行することです。

于 2014-02-25T22:05:50.357 に答える