-14

我的网络服务的一个子任务是在数据库中保存一个文件(连同一些元数据)。
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[]数组方式的解决方案。没有DatabaseField我可以用来设置的属性,dataType因为BYTE_ARRAY这在 Java 中是可能的。

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


我错过了什么重要的东西吗?
是否有另一种方法可以将文件放入数据库?

4

3 回答 3

5

因此,我认为您对 ServiceStack 内部的ORMLite和Java ORM 库的 ORMLite 感到困惑——它们既不相关也没有必要兼容。

您可能要问的是如何读取由 Java ORMLite 使用 C# ORMLite 编写的数据。我完全没有 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并覆盖负责将 CLR 值从 SQL 值转换为 SQL 值的函数以处理字节数组。

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 提供者,我分叉了 3.9.71 版的 Oracle 提供者,因为我需要使用 ODP.NET 库 (Oracle.DataAcess),因为我的项目正在进行一些 UDT 工作,并且需要 OracleParameter 对象上的 UDTType 对象。此外,我正在将压缩的专有“类似 xml”的字符串作为字节数组插入 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 回答