【问题标题】:is it possible to use sqlite manifest typing features in nhibernate?是否可以在 nhibernate 中使用 sqlite 清单类型功能?
【发布时间】:2009-07-31 17:07:12
【问题描述】:

这是在 hibernate.org 论坛和 nhusers 列表上发布的,但运气不佳,所以我想我会在这里尝试。

简单地说,假设我有一个班级:

class A
{
   public virtual object SomeValue { get; set; }
}

SomeValue 的类型基本上在 .NET IConvertible 类型的集合中(如 bool、byte、char、int16、double、float 等基元),加上 byte[] 和 string。

我正在尝试为 A 创建一个休眠映射以反映这一点 - 这样我基本上可以将 SomeValue 设置为任意对象(上述类型之一)并稍后检索它。然后我的 applogic 将对其进行反思以找到类型并做出相应的行为。

到目前为止,我已经尝试创建 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;
        }
    }

【问题讨论】:

  • 噢……你正在尝试做一些棘手的事情。祝你好运:你正在冒险进入复杂的水域。

标签: nhibernate sqlite nhibernate-mapping system.data.sqlite


【解决方案1】:

事实证明,方言不支持 SqlType(DbType.Object) 的问题,我们通过显式支持的 SQLiteDialect 子类化来支持它:

public class SQLiteDialectWithManifestTyping : SQLiteDialect
{
    public SQLiteDialectWithManifestTyping() : base()
    {
        base.RegisterColumnType(DbType.Object, "NONE");
    }
}

要在 Fluent 中使用这种方言,请在 SQLiteConfiguration 对象上调用 Dialect()。在 NHibernate 中,适当地设置配置属性 dialect(参见参考手册的第 3.5.1 节)。

然后我们可以为我们的映射应用上面的DataElementType实现(需要把SqlTypes定义改成这样:

    public SqlType[] SqlTypes
    {
        get
        {
            return new[] { new SqlType(DbType.Object) };
        }
    }

注意事项:

  1. 它并不完美。有一种趋势是将所有离散数字向上转换为 Int64 并浮点数加倍。

  2. 没有隐式的方法来存储大的无符号值(例如 ulong >= long.MaxValue 的值),但这是一般的 sqlite 问题(也可能是一般的 ado.net 问题?)。

  3. 由于编译时检查的损失,可能需要在 NullSafeSet 方法中进行一些运行时检查,以确保该值是原始类型。尝试存储一般对象似乎只会导致调用对象的 ToString() 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-04
    • 2018-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    相关资源
    最近更新 更多