إدراج قيم المفاتيح الأساسية باستخدام SUPOUND و SQLITE - مشكلة لأن Subund يعتقد أن الأعمدة إما تلقائيًا أم لا

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

سؤال

أنا أستخدم Subonic 2.2 و SQLite وواجهت مشكلة عند التعامل مع الجداول مع عمود مفتاح أساسي صحيح ليس تلقائيًا. بحسب ال التعليمات:

إذا أعلنت عمودًا من الجدول ليكون مفتاحًا أساسيًا صحيحًا ، فكلما قمت بإدخال خالية في هذا العمود من الجدول ، يتم تحويل الفارغ تلقائيًا إلى عدد صحيح وهو أكبر من أكبر قيمة لهذا العمود على جميع الصفوف الأخرى في الجدول ، أو 1 إذا كان الجدول فارغًا.

لذلك يعتقد sqlite أن هذه الأعمدة أحيانا زيادة تلقائية (أي فقط عند توفير القيم الفارغة). المشكلة هي أن Subsic يعتقد أنها كذلك دائماً زيادة السيارات.

في طلبي ، يتم إنشاء قيم المعرّف الخاصة بي من قاعدة بيانات عن بُعد ، لذلك لا أرغب في تلقائي في SQLite. يجب ألا تكون هذه مشكلة: سأقدم ببساطة قيمًا عندما أقوم بإنشاء سجلات في هذا الجدول. ومع ذلك ، عندما أستخدم sonic.exe من Subonic's Sonic's لتوظيف DAL الخاص بي ، يتم تعيين عمود المفتاح الأساسي على Autoincrement = true. يبدو أن هذا يعني أنه لا يمكنني تعيين عمود المعرف - ActiveHelper.getInserTCommand () يتجاهله ، لأنه يعتقد أنه تم إنشاؤه تلقائيًا.

الخط الذي يحدد ما إذا كان هو التلقائي أو لا هو في subsonic.sqlitedataprovider.getTablesChema ():

column.AutoIncrement = Convert.ToBoolean(row["PRIMARY_KEY"]) && GetDbType(row["DATA_TYPE"].ToString()) == DbType.Int64;

أعتقد أن الحل هو إما

  • لا تستخدم أعمدة مفاتيح INTEGER الأساسية للمفاتيح التي يتم إنشاؤها في مكان آخر ، أو

  • تعديل القوالب بحيث لا يتم ضبط هذه الأنواع من الأعمدة على التلقائي = صحيح. قد يعني هذا أن Subsong Song لن يعاملهم أبدًا على أنه زيادة السيارات ، لذلك أحتاج إلى توخي الحذر من أنني لا أتوقع لاحقًا الحصول على قيم تم إنشاؤها تلقائيًا. لسوء الحظ ، لا أعتقد أنه من الممكن داخل القوالب تحديد ما إذا كان العمود حقًا هو التلقائي حقًا أم لا ، لذلك ربما يتعين علي القيام ببعض الترميز القبيح بدلاً من ذلك ....

أي أفكار أو اقتراحات أخرى؟

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

المحلول

لسوء الحظ ، يبدو أن sqlitedataprovider لدينا يفترض أنه إذا كان INT64 PK ، فإنه يكون تلقائيًا. أنا أبحث عن المصدر الآن (لم أكتب هذا المزود) ويمكنني أن أرى أن الطريقة التي يتم تحميل المخطط بها تستخدم Connection.GetSchema - الذي يستخدم System.data.common.dbconnection للحصول على المخطط للجداول.

هذا هو دون المستوى الأمثل معظم الوقت لأنه يعيد معلومات محدودة. في هذه الحالة - لا يخبرنا ما إذا كان العمود تلقائيًا أم لا. من المحتمل أن يكون هناك طريقة أفضل لسؤال SQLite معلومات التعريف على الطاولة - لكنها لم تستخدم للأسف.

إجابة قصيرة: حدد PK جديد ، إذا كنت تستطيع ، واستخدم المفتاح الآخر كمرجع.

نصائح أخرى

كما ذكرت من قبل ، راجعت في Sqlitedataprovider المنقحة في ديسمبر. تحقق من ذلك في السطر 407 في sqlitedataprovider.cs لديك:

// اكتشاف AutoIncrement متاح الآن في System.Data.sqlite الحديثة. 1.0.60.0 - paul column.autoincrement = convert.toboolean (row ["Autoincrement"]) ؛

هناك أيضًا العديد من التحسينات الأخرى وإصلاحات الأخطاء في الخطوط المحيطة. لم تتم إضافة الرمز الجديد إلى توزيع المشروع الرئيسي في Github على ما أعتقد ، لا أتابع المشروع كثيرًا. لقد كان SQLite مزودًا رائعًا بصرف النظر عن قفل مستوى الملف. لديّ نسخة منزلية من System.Data.Sqlite التي تستخدم ميزات المفاتيح الخارجية الجديدة لـ SQLite ، ويجب إجراء الإصدار الرسمي هذا الشهر؟

ها هي النسخة المنقحة:sqlitedataprovider.cs

راجع للشغل ، تحقق من هذا المشروع في حال كنت بحاجة إلى التحويل من SQL Server:

تحويل SQL Server DB إلى SQLite DBhttp://www.codeproject.com/kb/database/convsqlservertosqlite.aspx

أجد أنه لا يمكنني استخدام CreateConnection مكتوب كما في SQLDATAPROVIDER بسبب قفل الملف. CreateConnection في sqlitedataprovider كما هو خاطئ الآن لأنه يتجاهل سلاسل اتصال جديدة.

يقول System.data.sqlite Doc "يمكنك إنشاء مؤشرات ترابط متعددة ، ويمكن أن تنشئ هذه المواضيع SQLitEconnection الخاصة بها والكائنات اللاحقة للوصول إلى قاعدة بيانات. توصيلات متعددة على مؤشرات ترابط متعددة إلى نفس ملف قاعدة البيانات مقبول تمامًا وستتصرف."

لذا فإن ما جربته هو ما يلي ، وهو حقًا مضرب. استخدم قاموس الاتصالات المفتاح بواسطة معرف الخيط وسلسلة الاتصال. لكن جميع اختبارات الوحدة تمر ، بما في ذلك معظم المعاملات (تحتاج إلى اختبارات أفضل). لقد كتبت اختبارات أخرى للمعاملات ، مع أقفال القسم الحرجة ، وأعتقد أنها قد تكون آمنة خيط ، فقط تحتاج إلى اختبارات أكثر واقعية.

private Dictionary<string, SQLiteConnection> threadConnectionTable = new Dictionary<string, SQLiteConnection>();

public override DbConnection CreateConnection(string newConnectionString)
{
    SQLiteConnection conn;
    string connKey = "t" + Thread.CurrentThread.ManagedThreadId + "__" + newConnectionString;
    if(threadConnectionTable.ContainsKey(connKey))
    {
        conn = threadConnectionTable[connKey];
        if(conn.State != ConnectionState.Open)
            conn.Open();
        return conn;
    }
    conn = new SQLiteConnection(newConnectionString);
    conn.Open();
    threadConnectionTable[connKey] = conn;
    return conn;
}



private Object thisLock = new Object();

[Test]
[ThreadedRepeat(10)]
public void MultiThreadRepeat()
{
    lock(thisLock)
    {
        var qcc = new QueryCommandCollection();
        int threadId = Thread.CurrentThread.ManagedThreadId;
        Debug.WriteLine("MultiThreadRepeat: thread id = " + threadId);
        int count = 0;
        for(int n = 0; n < 10; n++)
        {
            Query qry1 = new Query(Product.Schema);
            qry1.QueryType = QueryType.Update;
            qry1.AddWhere(Product.Columns.ProductID, n);
            qry1.AddUpdateSetting("ProductName", threadId + ": unit test ");
            QueryCommand cmd = qry1.BuildUpdateCommand();
            qcc.Add(cmd);
            count++;
        }
        DataService.ExecuteTransaction(qcc);
        var p1 = new Product(1);
        Assert.AreEqual(p1.ProductName, threadId + ": unit test ", StringComparison.InvariantCultureIgnoreCase);
    }

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