سؤال

أنا أستخدم nhibernate لتخزين بعض إعدادات المستخدم لأحد التطبيقات في جدول SQL Server Compact Edition.

هذا مقتطف من ملف التعيين:

<property name="Name" type="string" />
<property name="Value" type="string" />

الاسم عبارة عن سلسلة عادية/nvarchar(50)، ويتم تعيين القيمة كنص ntext في قاعدة البيانات

أحاول كتابة كمية كبيرة من ملف XML إلى خاصية "القيمة".أحصل على استثناء في كل مرة:

@p1 : String truncation: max=4000, len=35287, value='<lots of xml..../>'

لقد بحثت في Google كثيرًا، وحاولت عددًا من تكوينات الخرائط المختلفة:

<property name="Name" type="string" />
<property name="Value" type="string" >
  <column name="Value" sql-type="StringClob" />
</property>

هذا مثال واحد.تتضمن التكوينات الأخرى "ntext" بدلاً من "StringClob".تلك التكوينات التي لا تطرح استثناءات التعيين ستستمر في طرح استثناء اقتطاع السلسلة.

هل هذه مشكلة ("ميزة") في SQL CE؟هل من الممكن وضع أكثر من 4000 حرف في قاعدة بيانات SQL CE باستخدام nhibernate؟إذا كان الأمر كذلك، هل يمكن لأحد أن يقول لي كيف؟

تشكرات!

هل كانت مفيدة؟

المحلول

حسنًا، مع جزيل الشكر لـ Artur in هذا الموضوع, ، إليك الحل:وراثة من SqlServerCeDriver بواحدة جديدة، وتجاوز طريقة التهيئة المعلمة:

using System.Data;
using System.Data.SqlServerCe;
using NHibernate.Driver;
using NHibernate.SqlTypes;

namespace MySqlServerCeDriverNamespace
{
    /// <summary>
    /// Overridden Nhibernate SQL CE Driver,
    /// so that ntext fields are not truncated at 4000 characters
    /// </summary>
    public class MySqlServerCeDriver : SqlServerCeDriver
    {
        protected override void InitializeParameter(
            IDbDataParameter dbParam,
            string name,
            SqlType sqlType)
        {
            base.InitializeParameter(dbParam, name, sqlType);

            if (sqlType is StringClobSqlType)
            {
                var parameter = (SqlCeParameter)dbParam;
                parameter.SqlDbType = SqlDbType.NText;
            }

        }
    }
}

ثم استخدم برنامج التشغيل هذا بدلاً من برنامج NHibernate في app.config الخاص بك

<nhibernateDriver>MySqlServerCeDriverNamespace.MySqlServerCeDriver , MySqlServerCeDriverNamespace</nhibernateDriver>

لقد رأيت الكثير من المشاركات الأخرى حيث واجه الأشخاص هذه المشكلة، وقمت بحلها بمجرد تغيير سمة نوع SQL إلى "StringClob" - كما تمت محاولته في هذا الموضوع.

لست متأكدًا من سبب عدم نجاح ذلك بالنسبة لي، ولكن أظن أن السبب هو حقيقة أنني أستخدم SQL CE وليس بعض قواعد البيانات الأخرى.ولكن هناك لديك!

نصائح أخرى

<property name="Value" type="string" />
  <column name="Value" sql-type="StringClob" />
</property>

أفترض أن هذا خطأ مطبعي بسيط، حيث أنك قمت بإغلاق علامة الخاصية مرتين.فقط أشير إلى هذا، في حالة أنه لم يكن خطأ مطبعي.

يحاول <property name="Value" type="string" length="4001" />

حاول:

<property name="Value" type="string" length="4001" />

و

<property name="Value" type="string" >
  <column name="Value" sql-type="StringClob" length="5000"/>
</property>

لم ينجح أي منهما، أخشى...نفس الاستثناء - لا يزال يقول أن القيمة القصوى هي 4000.

لماذا تستخدم بناء جملة العنصر الفرعي؟

يحاول:

<property name='Value' type='StringClob' />

في عملية التوزيع الحالية لـ SQL CE وNHibernate، أستخدم طولًا يبلغ 4001.ثم يقوم NHibernate بإنشاء العناصر كـ NTEXT بدلاً من NVARCHAR.

جرب ذلك.

شيء آخر يمكن استخدامه مع NHibernate وSQL CE هو:

<session-factory>
  ...
  <property name="connection.release_mode">on_close</property>
</session-factory>

وهذا يحل بعض المشاكل الأخرى بالنسبة لي على الأقل.

بعد قراءة رسالتك، أصبح هذا التعديل يعمل في الكود الخاص بي

protected override void InitializeParameter(IDbDataParameter dbParam,string name,SqlType sqlType)
    {
        base.InitializeParameter(dbParam, name, sqlType);

        var stringType = sqlType as StringSqlType;
        if (stringType != null && stringType.LengthDefined && stringType.Length > 4000)
        {
            var parameter = (SqlCeParameter)dbParam;
            parameter.SqlDbType = SqlDbType.NText;
        }

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