سؤال

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

واحدة من الميزات الرئيسية الأخرى للتطبيق هي القدرة على إنشاء استعلامات مخصصة ضد هذه الحقول المخصصة. يتم تحقيق ذلك من خلال واجهة مستخدم يمكن فيه إنشاء أي عدد من القواعد (التاريخ <= الآن - 5 أيام) ، نص مثل "444" ، المنسدلة == 'ICU'). جميع القواعد هي و "معا لإنتاج استعلام.

التنفيذ الحالي (الذي "ورثته") ليس موجهًا للكائن أو وحدة قابلة للاختبار. في الأساس ، هناك فئة واحدة "إله" تجمع جميع أنواع القواعد التي لا تعد ولا تحصى مباشرة في بيان SQL ديناميكي معقد (أي IE INNER ، الوصلات الخارجية ، والفروع). هذا النهج مزعج لعدة أسباب:

  • لا يكاد يكون اختبار القواعد الفردية بالوحدة مستحيلًا
  • هذه النقطة الأخيرة تعني أيضًا إضافة أنواع القواعد الإضافية في المستقبل من المؤكد أن تنتهك المبدأ المغلق المفتوح.
  • يتم مشاركة منطق العمل والمستمر.
  • اختبارات وحدة التشغيل البطيئة نظرًا لأن قاعدة بيانات حقيقية مطلوبة (لا يمكن SQLLITE تحليل T-SQL والسخرية من المحلل سيكون UHH ... صعب)

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

أنا أفكر في مجموعة من أنماط القيادة وسلسلة المسؤولية:

تحتوي فئة الاستعلام على مجموعة من فئات القواعد التجريدية (Daterule ، Textrule ، إلخ). ويحمل إشارة إلى فئة مجموعة البيانات التي تحتوي على مجموعة من البيانات غير المصفاة. تم تصميم مجموعة البيانات بأسلوب لا أدري (أي لا توجد مراجع أو خطافات في أنواع قاعدة البيانات)

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

الشيء الوحيد الذي يقلقني بشأن هذا النهج هو الآثار المترتبة على أداء مجموعة بيانات كبيرة غير مرفقة محتملة في .NET. من المؤكد أن هناك بعض الأساليب المجربة والحقيقية لحل هذا النوع من المشكلات التي توفر توازنًا جيدًا بين القدرة على الصيانة والأداء؟

ملاحظة أخيرة: لن تسمح الإدارة باستخدام nhibernate. قد يكون من الممكن أن يكون LINQ إلى SQL ، لكنني لست متأكدًا من مدى تنفيذ هذه التكنولوجيا في المهمة المطروحة.

شكرا جزيلا وأنا أتطلع إلى ملاحظات الجميع!

تحديث: لا تزال تبحث عن حل على هذا.

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

المحلول

أعتقد أن LINQ إلى SQL سيكون حلًا مثاليًا مقترنًا ، ربما ، مع LINQ الديناميكي من عينات VS2008. باستخدام LINQ ، لا سيما مع طرق التمديد على ienumerable/iqueryable ، يمكنك بناء استعلاماتك باستخدام المنطق القياسي والمخصص الخاص بك اعتمادًا على المدخلات التي تحصل عليها. أستخدم هذه التقنية بشكل كبير لتنفيذ المرشحات على العديد من إجراءات MVC الخاصة بي لتأثير كبير. نظرًا لأنه يبني بالفعل شجرة تعبير ثم يستخدمها لإنشاء SQL في النقطة التي يحتاج فيها الاستعلام إلى تحقيقها ، أعتقد أنه سيكون مثاليًا للسيناريو الخاص بك لأن معظم الرفع الثقيل لا يزال يتم بواسطة SQL Server. في الحالات التي يثبت فيها LINQ إنشاء استعلامات غير مثالية ، يمكنك دائمًا استخدام وظائف ذات قيمة الجدول أو الإجراءات المخزنة التي تمت إضافتها إلى سياق بيانات LINQ الخاص بك كطرق للاستفادة من الاستعلامات المحسنة.

محدث: قد تحاول أيضًا استخدام ProseTbuilder من C# 3.0 باختصار.

مثال: ابحث عن جميع الكتب التي يحتوي عليها العنوان واحدة من مجموعة من مصطلحات البحث والناشر هو O'Reilly.

 var predicate = PredicateBuilder.True<Book>();
 predicate = predicate.And( b => b.Publisher == "O'Reilly" );
 var titlePredicate = PredicateBuilder.False<Book>();
 foreach (var term in searchTerms)
 {
     titlePredicate = titlePredicate.Or( b => b.Title.Contains( term ) );
 }
 predicate = predicate.And( titlePredicate );

 var books = dc.Book.Where( predicate );

نصائح أخرى

الطريقة التي رأيتها بها هي إنشاء كائنات تصمم كل من الشروط التي تريد أن يقوم المستخدم بإنشائها من استفسارهم ، وإنشاء شجرة من الكائنات باستخدام تلك.

من شجرة الكائنات ، يجب أن تكون قادرًا على إنشاء بيان SQL بشكل متكرر يرضي الاستعلام.

ستكون الأشياء الأساسية التي ستحتاجها و / أو الكائنات ، وكذلك الكائنات لمقارنة النماذج ، مثل متساوٍ ، Lessthan وما إلى ذلك. ربما ترغب في استخدام واجهة لهذه الكائنات لجعل التسلسل معًا بطرق مختلفة أسهل.

مثال تافهة:

public interface IQueryItem
{
    public String GenerateSQL();
}


public class AndQueryItem : IQueryItem
{
    private IQueryItem _FirstItem;
    private IQueryItem _SecondItem;

    // Properties and the like

    public String GenerateSQL()
    {
        StringBuilder builder = new StringBuilder();
        builder.Append(_FirstItem.GenerateSQL());
        builder.Append(" AND ");
        builder.Append(_SecondItem.GenerateSQL());

        return builder.ToString();
    }
}

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

على الجانب السلبي ، لا يزال هذا الحل يترك قاعدة البيانات للقيام بالكثير من العمل ، والذي يبدو أنك لا تريد فعل ذلك حقًا.

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