Frage

Dieses wurde ohne viel Glück auf hibernate.org Foren und nhusers Liste geschrieben, so dass ich dachte, ich würde versuchen hier.

Einfach gesagt, denke ich habe eine Klasse:

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

die Art der EinWert ist im Grunde in dem Satz von .NET IConvertible Typen (Primitiven wie Bool, Byte, Saibling, int16, double, float usw.) sowie byte [] und String zurück.

Ich versuche, eine nhibernate Zuordnung erstellen für A, dies zu reflektieren - so dass ich im Grunde EinWert auf ein beliebiges Objekt festlegen kann (von einem des Typ oben) und rufen Sie sich später auf. Mein AppLogic wird dann darüber nachdenken, den Typ zu finden und sich entsprechend zu verhalten.

Bisher habe ich versucht, eine Implementierung von IUserType erstellen, um zu versuchen und damit zu umgehen. Allerdings weiß ich nicht, was für die SQLType [] SqlTypes zurückzukehren. Ich betrachtete neue SQLType (DbType.Object), aber wenn ich versuche, ein Schema aus dieser ich eine System.ArgumentException erhalten zu generieren: Dialect nicht unterstützt DbType.Object

Wenn ich einen anderen Datentyp versuchen dann bekomme ich verschiedene Ausnahmen Besetzung beim Versuch, den Typ zu konvertieren. wenn ich zum Beispiel verwenden, um eine DbType.Binary und setzen somevalue auf einen int32, beim Versuch zu begehen ich System.InvalidCastException. Konnte nicht das Objekt des Typs ‚System.Int32‘ werfen ‚System.Byte []‘ eingeben

Gibt es eine Möglichkeit, dies zu erreichen?

Angehängte Code unten für eine nicht-funktionierende Implementierung von IUserType (basierend auf 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;
        }
    }
War es hilfreich?

Lösung

Es dreht sich um das Problem raus mit SQLType (DbType.Object) durch die Dialect ungestützt ist, machen wir es unterstützt durch die SQLiteDialect mit expliziter Unterstützung Subklassen:

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

Um diesen Dialekt in Fluent zu verwenden, rufen Dialect () auf Ihrem SQLiteConfiguration Objekt. In NHibernate, setzen Sie den Konfigurationseigenschaften Dialekt appropriatelly (Abschnitt 3.5.1 der ref Handbuch).

Dann können wir die oben DataElementType Implementierung für unsere Zuordnungen gelten (müssen die SqlTypes Definition, dies zu ändern:

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

Weitere Informationen:

  1. Es ist nicht perfekt. Es gibt eine Tendenz, alle diskreten Zahlen Int64 upCast und schwimmt zu verdoppeln.

  2. Es gibt keine implizite Möglichkeit zu speichern große Werte ohne Vorzeichen (zB Werte von ulong> = long.MaxValue), aber dies ist ein allgemeines Problem SQLite (und möglicherweise ein allgemeines ado.net Problem?).

  3. Durch den Verlust der Kompilierung überprüft es wahrscheinlich wünschen ist, einige Laufzeitprüfungen im NullSafeSet Methode setzen Sie den Wert, um sicherzustellen, ist ein Urtyp. allgemeine Objekte zu speichern versuchen, scheint nur die Objekte verursachen Methode toString () aufgerufen werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top