سؤال

أي شخص لديه تقديم المشورة جيدة حول كيفية تنفيذ تعيين واحد إلى كثير SQLite استخدام ContentProviderب إذا نظرت في Uri ContentProvider#insert(Uri, ContentValues) يمكنك أن ترى أنه لديه ContentValues param التي تحتوي على بيانات لإدراجها. المشكلة هي أنه في تنفيذها الحالي ContentValues لا يدعم put(String, Object) الطريقة والصفة نهائية لذلك لا أستطيع تمديدها. لماذا هي مشكلة؟ هنا يأتي تصميمي:

لدي 2 طاولات هي في علاقة واحدة إلى كثير. لتمثيل هذه التعليمات البرمجية لدي كائنات نموذجية. يمثل 1st السجل الرئيسي ولديه حقل هو قائمة مثيلات الكائنات الثانية. الآن لدي طريقة مساعد في كائن النموذج رقم 1 الذي يعود ContentValues ولدت خارج الكائن الحالي. انها تافهة لتعبئة الحقول البدائية مع ContentValues#put الطرق الزائدة ولكن أنا خارج التوفيق في القائمة. حتى الآن نظرا لأن صفي الثاني للجدول الثاني هو مجرد قيمة سلسلة واحدة تولد سلسلة محددة بفواصل ثم تمت إعادة التوصل إلى سلسلة [] في الداخل ContentProvider#insert. وبعد هذا يشعر يوكي، لذلك ربما يمكن لشخص ما تلميح كيف يمكن القيام به في الأزياء الأنظف.

إليك بعض الكود. أولا من فئة النموذج:

public ContentValues toContentValues() {
    ContentValues values = new ContentValues();
    values.put(ITEM_ID, itemId);
    values.put(NAME, name);
    values.put(TYPES, concat(types));
    return values;
}

private String concat(String[] values) { /* trivial */}

وهنا نسخة خفضت أسفل ContentProvider#insert طريقة

public Uri insert(Uri uri, ContentValues values) {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    db.beginTransaction();
    try {
        // populate types
        String[] types = ((String)values.get(Offer.TYPES)).split("|");
        // we no longer need it
        values.remove(Offer.TYPES);
        // first insert row into OFFERS
        final long rowId = db.insert("offers", Offer.NAME, values);
        if (rowId > 0 && types != null) {
            // now insert all types for the row
            for (String t : types) {
                ContentValues type = new ContentValues(8);
                type.put(Offer.OFFER_ID, rowId);
                type.put(Offer.TYPE, t);
                // insert values into second table
                db.insert("types", Offer.TYPE, type);
            }
        }
        db.setTransactionSuccessful();
        return ContentUris.withAppendedId(Offer.CONTENT_URI, rowId);
    } catch (Exception e) {
        Log.e(TAG, "Failed to insert record", e);
    } finally {
        db.endTransaction();
    }

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

المحلول

أعتقد أنك تبحث في الطرف الخطأ من العلاقة الواحدة والعديدة.

نلقي نظرة على ContactsContract مزود المحتوى، على سبيل المثال. يمكن أن تحتوي جهات الاتصال على العديد من عناوين البريد الإلكتروني والعديد من أرقام الهواتف، إلخ. الطريقة التي يتم إنجازها هي القيام بإدراج / تحديثات / حذف "عديدة" الجانب. لإضافة رقم هاتف جديد، تقوم بإدراج رقم هاتف جديد، مما يوفر معرفا للاتصال الذي يتعلق به رقم الهاتف.

يمكنك أن تفعل الشيء نفسه إذا كان لديك قاعدة بيانات SQLite عادي بدون موفر محتوى. يتم تحقيق علاقات واحدة إلى عديدة في قواعد البيانات العلائقية عبر إدراج / تحديثات / حذف على جدول للجانب "العديد من"، كل منها يحتوي على مفتاح أجنبي إلى جانب "واحد".

الآن، من وجهة نظر OO، هذا ليس مثاليا. اهلا وسهلا بكم لإنشاء كائنات المجمع على غرار Orm (فكر في السبات) تتيح لك معالجة مجموعة من الأطفال من الجانب "واحد". يمكن بعد ذلك تشغيل فئة مجموعة ذكية بما فيه الكفاية ومزامنة الجدول "العديد" للمطابقة. ومع ذلك، فإن هذه ليست تافهة بالضرورة لتنفيذها بشكل صحيح.

نصائح أخرى

يمكنك استخدام ContentProviderOperations لهذا.

إنهم في الأساس العمليات بالجملة مع القدرة على العودة إلى المراجع إلى المعرفات الناتجة عن الصفوف الأصل.

كيف ContentProviderOperations يمكن استخدامها لتصميم واحد إلى كثير يفسر جيدا في هذه الإجابة: ما هي دلالات withvaluebackReference؟

لذلك سأجيب على سؤالي الخاص. كنت على المسار الصحيح مع وجود جدولين واثنين من الكائنات النموذجية. ما كان مفقودا وما في حيرة مني كان أرغب في إدراج بيانات معقدة مباشرة ContentProvider#insert في مكالمة واحدة. هذا خطأ. ContentProvider يجب إنشاء وصيانة هذين الجدولين ولكن القرار الذي يجب أن يملي به جدول يستخدمه المعلمة URI ContentProvider#insert. وبعد إنه مناسب جدا لاستخدام ContentResolver وأضف طرق مثل "AddFoo" إلى كائن النموذج. هذه الطريقة ستأخذ المعلمة QuestentResolver وفي النهاية هنا هي التسلسل لإدراج سجل معقد:

  1. إدراج سجل الوالدين من خلال ContentProvider#insert والحصول على معرف التسجيل
  2. لكل طفل يوفر المعرف الأصل (Foregn Key) واستخدامه ContentProvider#insert مع مختلف URI لإدراج سجلات الأطفال

وبالتالي فإن السؤال الوحيد المتبقي هو كيفية مغلف رمز أعلاه في المعاملة؟

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