是否可以在 nhibernate 中使用 sqlite 清单输入功能?
这是张贴在 hibernate.org 论坛和 nhusers 列表上的,但运气不佳,所以我想我会在这里尝试一下。
简而言之,假设我有一个类:
class A
{
public virtual object SomeValue { get; set; }
}
SomeValue 的类型基本上位于 .NET IConvertible 类型集中(像 bool、byte、char、int16、double、float 等基元),加上 byte[] 和 string。
我正在尝试为 A 创建一个 nhibernate 映射来反映这一点 - 这样我基本上可以将 SomeValue 设置为任意对象(上述类型之一)并稍后检索它。 然后,我的应用程序逻辑将对其进行反思以查找类型并相应地表现。
到目前为止,我已经尝试创建 IUserType 的实现来尝试处理这个问题。 但是我不知道 SqlType[] SqlTypes 返回什么。 我考虑过 new SqlType(DbType.Object) 但是当我尝试从中生成模式时,我得到一个 System.ArgumentException: Dialect does not support DbType.Object
如果我尝试其他数据类型,那么在尝试转换时会得到各种强制转换异常类型。 例如,如果我使用 DbType.Binary,并将 someValue 设置为 int32,则在尝试提交时,我会得到 System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.Byte[]'。
有办法实现这一点吗?
下面附加了 IUserType 的非工作实现的代码(基于 http: //intellect.dk/post/Implementing-custom-types-in-nHibernate.aspx )
public class DataElementType : IUserType
{
SqlType baseType = new SqlType(DbType.Binary);
public SqlType[] SqlTypes
{
get
{
return new[] { baseType };
}
}
public System.Type ReturnedType
{
get { return typeof(object); }
}
public new bool Equals(object x, object y)
{
if (x == null)
return false;
else
return x.Equals(y);
}
public int GetHashCode(object x)
{
return x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
return rs[names[0]];
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
var param = new SQLiteParameter(baseType.DbType, value);
cmd.Parameters.Insert(index, param);
}
public object DeepCopy(object value)
{
if (value == null) return null;
return value;
}
public bool IsMutable
{
get { return false; }
}
public object Replace(object original, object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
return cached;
}
public object Disassemble(object value)
{
return value;
}
}
this was posted on hibernate.org forums and nhusers list without much luck, so I thought I would try here.
Put simply, suppose I have a class:
class A
{
public virtual object SomeValue { get; set; }
}
the type of SomeValue is basically in the set of .NET IConvertible types (primitives like bool, byte, char, int16, double, float etc.), plus byte[] and string.
I am trying to create a nhibernate mapping for A to reflect this - so that I can basically set SomeValue to an arbitrary object (of one of the types above) and retrieve it later on on. My applogic will then reflect on it to find the type and behave accordingly.
So far I have tried Creating an implementation of IUserType to try and handle this. However I don't know what to return for the SqlType[] SqlTypes. I considered new SqlType(DbType.Object) but when I try to generate a schema from this I get a System.ArgumentException: Dialect does not support DbType.Object
If I try another data type then I get various cast exceptions when trying to convert the type. For instance if i use a DbType.Binary, and set someValue to an int32, upon attempting to commit I get System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.Byte[]'.
Is there a way to achieve this?
Attached code below for a non-working implementation of IUserType (based on http://intellect.dk/post/Implementing-custom-types-in-nHibernate.aspx )
public class DataElementType : IUserType
{
SqlType baseType = new SqlType(DbType.Binary);
public SqlType[] SqlTypes
{
get
{
return new[] { baseType };
}
}
public System.Type ReturnedType
{
get { return typeof(object); }
}
public new bool Equals(object x, object y)
{
if (x == null)
return false;
else
return x.Equals(y);
}
public int GetHashCode(object x)
{
return x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
return rs[names[0]];
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
var param = new SQLiteParameter(baseType.DbType, value);
cmd.Parameters.Insert(index, param);
}
public object DeepCopy(object value)
{
if (value == null) return null;
return value;
}
public bool IsMutable
{
get { return false; }
}
public object Replace(object original, object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
return cached;
}
public object Disassemble(object value)
{
return value;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
事实证明,为了解决方言不支持 SqlType(DbType.Object) 的问题,我们通过显式支持 SQLiteDialect 子类来支持它:
要在 Fluent 中使用此方言,请在 SQLiteConfiguration 对象上调用 Dialect() 。 在 NHibernate 中,适当地设置配置属性 dialect(请参阅参考手册的第 3.5.1 节)。
然后我们可以将上面的 DataElementType 实现应用于我们的映射(需要将 SqlTypes 定义更改为:
注意:
它并不完美。有一种趋势是将所有离散数字向上转换为 Int64,将浮点数转换为 double。
没有隐式方法来存储大型无符号值(例如 ulong >= long.MaxValue 的值)。一般的 sqlite 问题(也可能是 ado.net 的一般问题?)。
由于编译时检查的丢失,可能需要在 NullSafeSet 方法中进行一些运行时检查,以确保该值是原始类型。只是导致对象 ToString() 方法被调用。
It turns out to get around the problem with SqlType(DbType.Object) being unsupported by the Dialect, we make it supported by subclassing the SQLiteDialect with explicit support:
To use this dialect in Fluent, call Dialect() on your SQLiteConfiguration object. In NHibernate, set the configuration property dialect appropriatelly (see section 3.5.1 of the ref manual).
Then we can apply the above DataElementType implementation for our mappings (need to change the SqlTypes definition to this:
Notes:
It is not perfect. There is a tendency to upcast all discrete numbers to Int64 and floats to double.
There is no implicit way to store large unsigned values (e.g. values of ulong >= long.MaxValue) but this is a general sqlite problem (and possible a general ado.net problem?).
Due to the loss of compile time checking it is probably desireable to put some runtime checks in the NullSafeSet method to ensure the value is a primitive type. Attempting to store general objects seems to just cause the objects ToString() method to be called.