Oracle非空BLOB列插入byte[0]失败,NHibernate报ORA-01400错误求助
NHibernate插入空BLOB到Oracle NOT NULL字段报错ORA-01400的解决办法
这个问题我之前碰到过,核心原因是NHibernate把空byte数组(new byte[0])当成NULL值处理了,但Oracle的NOT NULL约束不认这个——而你用PL/SQL里的empty_blob()时,其实是创建了一个合法的空BLOB对象(不是NULL),所以能绕过约束。
下面给你几个可行的解决办法,按需选择:
1. 映射层指定默认值为empty_blob()
最省事的方式是在实体映射里直接给DOCUMENT列设置默认值为Oracle的empty_blob(),这样不管你有没有给document属性赋值,NHibernate都会自动用合法的空BLOB填充。
如果是XML映射文件:
<property name="document" column="DOCUMENT" type="BinaryBlob"> <column name="DOCUMENT" default="empty_blob()"/> </property>
如果用Fluent NHibernate配置:
Map(x => x.document).Column("DOCUMENT").Default("empty_blob()");
2. 代码中手动创建NHibernate可识别的空BLOB
保存实体时,别用new byte[0],而是通过NHibernate的Session创建一个空BLOB对象,这个对象会对应Oracle的empty_blob():
using (var session = SessionFactory.OpenSession()) { Document documentDomain = new Document(); documentDomain.doc_url = "http://path_to_the_document"; // 创建对应empty_blob()的BLOB实例 documentDomain.document = session.CreateBlob(new MemoryStream()); session.Save(documentDomain); }
3. 自定义NHibernate类型自动处理空数组
如果你的项目里经常要处理这种场景,可以写个自定义类型,自动把空byte数组转换成empty_blob():
public class OracleEmptyBlobType : BinaryBlobType { public override void Set(IDbCommand cmd, object value, int index) { var bytes = value as byte[]; if (bytes != null && bytes.Length == 0) { var oracleCmd = cmd as OracleCommand; oracleCmd.Parameters[index].OracleDbType = OracleDbType.Blob; oracleCmd.Parameters[index].Value = OracleBlob.Empty; } else { base.Set(cmd, value, index); } } }
然后在映射里使用这个自定义类型:
<property name="document" type="YourNamespace.OracleEmptyBlobType, YourAssembly"/>
补充:为啥PL/SQL能成功?
Oracle的empty_blob()函数返回的是一个空的BLOB对象实例,它本质上是一个非NULL的对象,完全符合NOT NULL约束。但NHibernate默认会把空byte数组解析成SQL里的NULL,这就直接触发了约束报错——这就是两者的核心差异。
内容的提问来源于stack exchange,提问作者Dinny
相关产品推荐
相关产品推荐

