هل من الممكن استخدام ميزات الكتابة الواضحة لـ sqlite في nhibernate؟

StackOverflow https://stackoverflow.com/questions/1213728

سؤال

تم نشر هذا في منتديات hibernate.org وقائمة nhusers دون حظ كبير، لذلك اعتقدت أنني سأحاول هنا.

ببساطة، لنفترض أن لدي فصل دراسي:

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

نوع SomeValue موجود بشكل أساسي في مجموعة أنواع .NET IConvertible (الأوليات مثل bool، byte، char، int16، double، float وما إلى ذلك)، بالإضافة إلى byte[] وstring.

أحاول إنشاء تعيين nhibernate لـ A ليعكس هذا - حتى أتمكن بشكل أساسي من تعيين SomeValue على كائن عشوائي (من أحد الأنواع المذكورة أعلاه) واستعادته لاحقًا.سوف يتأمل تطبيقي بعد ذلك للعثور على النوع والتصرف وفقًا لذلك.

لقد حاولت حتى الآن إنشاء تطبيق IUserType لمحاولة التعامل مع هذا الأمر.ومع ذلك لا أعرف ما الذي يجب إرجاعه لـ SqlType[] SqlTypes.لقد فكرت في SqlType (DbType.Object) الجديد ولكن عندما أحاول إنشاء مخطط من هذا أحصل على System.ArgumentException:اللهجة لا تدعم DbType.Object

إذا حاولت نوع بيانات آخر، فسأحصل على استثناءات مختلفة عند محاولة تحويل النوع.على سبيل المثال، إذا استخدمت DbType.Binary، وقمت بتعيين someValue على int32، عند محاولة الالتزام أحصل على System.InvalidCastException:غير قادر على تحويل كائن من النوع "System.Int32" لكتابة "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;
        }
    }
هل كانت مفيدة؟

المحلول

لقد اتضح أنه للتغلب على مشكلة عدم دعم SqlType(DbType.Object) بواسطة Dialect، فإننا نجعلها مدعومة من خلال تصنيف SQLiteDialect إلى فئة فرعية بدعم صريح:

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

لاستخدام هذه اللهجة في Fluent، اتصل بـ Dialect() على كائن SQLiteConfiguration الخاص بك.في NHibernate، قم بتعيين لهجة خاصية التكوين بشكل مناسب (راجع القسم 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() للكائنات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top