如何使用ORMlite将byte[]数组插入到image列中



我的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[]数组的方式的解决方案。没有属性DatabaseField可以用来将dataType设置为BYTE_ARRAY,因为这在Java中是可能的。

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


我错过了一些重要的东西吗
有没有其他方法可以将文件放入数据库?

所以我认为您混淆了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[])

它从具有results.getBytes(columnPos)的结果中检索byte[]

你提到:

ORMlite将字节数组转换为base64编码的字符串

这是JDBC在做这件事。我很惊讶,但我想这是可能的。

希望这里有什么帮助。

在ServiceStack.OrmLite v4中,正如mythz在注释中所指定的那样,一切都应该正常工作。


在v3中,如果希望将字节数组序列化为二进制而不是基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();

对于Oracle提供程序,我分叉了Oracle提供程序的3.9.71,因为我的项目正在做一些UDT工作,需要使用ODP.NET库(Oracle.DataAcess),并且需要OracleParameter对象上的UDTType对象。此外,我还在BLOB列中插入一个压缩的专有"类xml"字符串作为字节数组。

在我的项目中,我使用

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。

最新更新