الأداء بخصوص نوع الإرجاع لاستعلام LINQ متوافق مع الفرز التلقائي

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

سؤال

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

WinForms C# .NET3.5 [SP1] Visual Studio 2008 باستخدام LINQ2SQL (بشكل أكثر تحديدًا Plinqo... وهو رائع راجع للشغل!). لديّ ResultSet Return +/- 19000 صف من البيانات (مع حوالي 80Bytes من البيانات لكل صف) واختارت دفع طريقة استرجاع البيانات إلى الخلفية وتحديث واجهة المستخدم وفقًا لذلك. هذا يعمل بشكل جيد.

ومع ذلك ، لاحظت بعض الاختلافات في الأداء عند استخدام أنواع الإرجاع المختلفة لطريقة استرجاع بيانات Ling الخاصة بي. أعلم أن كل شخص يقترح إرجاع أ List<T> أو IEnumarable<T>, ، وتعيين بيانات بيانات DataGridView على ذلك ، ولكن للأسف لا تدعم الفرز أصلاً للكائنات. بعد بعض الحفر حولها وجدت SortableBindingList<T> على MSDN هنا. لقد قمت بتطبيقه ، واستغرق الشبكة تحت ثانية لإلغاء نفسها - ولكن عندما أنقر على عمود لفرزه ، استغرق الأمر أكثر بقليل من ثانية أو نحو ذلك لتنفيذ هذا النوع.

قررت بعد ذلك الذهاب إلى مسار DataTable ، لكنني اكتشفت أنه تمت إزالة طريقة todatable ، ولكن بعد مزيد من الحفر وجدت طريقة لتنفيذها على هذا مقال MSDN. بعد تطبيقه ، اكتشفت أن الاسترجاع استغرق حوالي ثانيتين لإلغاء الشبكة ، ولكن بعد ذلك كان الفرز (في 19000 صف!) فوريًا !! بطبيعة الحال ، تمسك بهذا النهج.

ضع في اعتبارك أيضًا أنني قمت بتعطيل أي تحرير/إضافة/حذف الشبكة. الشبكة بحتة لعرض البيانات. يتم توفير أي عمليات أخرى CRUD بواسطة نماذج الحوار وفقًا للصف الحالي المحدد (عمود المفتاح الأساسي المخفي).

فيما يلي الرمز الذي استخدمته لكلا الطريقتين:

1) LortableBindingList

    //declare private member
    private SortableBindingList<PdtAllocation> listAlloc = null;

    private void RefreshData() {
        bcsDataContext ctx = new bcsDataContext();
        try {
            listAlloc = new SortableBindingList<PdtAllocation>(ctx.PdtAllocation.ToList());
        }
        catch (Exception) {
            throw;
        }
        finally {
            ctx.Dispose();
        }

        dataGridView1.DataSource = listAlloc;
    }

2) copleTodataTable

    //declare private member
    private DataTable dt = null;

    private void RefreshData() {
        dt = new DataTable();
        bcsDataContext ctx = new bcsDataContext();
        try {
            ctx.PdtAllocation.CopyToDataTable(dt, LoadOption.PreserveChanges);
        }
        catch (Exception) {
            throw;
        }
        finally {
            ctx.Dispose();
        }

        dataGridView1.DataSource = dt;
    }

الآن أعلم أن هذا ربما يبدو وكأنه "طلب وجواب"الحالة ، لكنني أقدر حقًا مدخلاتك ، وكذلك أي مشكلات معروفة في الذهاب CopyToDataTable() طريق.

شكرا لك .... والاعتذار عن الاستعلام الأسطوري!

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

المحلول

هذا هو رأيي على سؤالك (الذهاب SortableBindingList طريق).

هل استخدمت خوارزمية فرز عامة قائمة على الانعكاس؟ لقد فعلت هذا في البداية وكان الأداء سيئًا حقًا. أخيرًا ، توصلت إلى الحل التالي: قدم الفرز الافتراضي في SortableBindingList<T> ولكن ترك أيضًا إمكانية تنفيذ الفرز المتخصص في الفصول المشتقة.

إليك بعض الكود.

في SortableBindingList<T>.ApplySortCore():

protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
    // Check if the sorted property implements IComparable
    ...

    List<T> itemsList = (List<T>)this.Items;

    Comparison<T> comparer = GetComparer(prop);

    itemsList.Sort(comparer);

    if (direction == ListSortDirection.Descending)
    {
        itemsList.Reverse();
    }

    ...
    // Set sort state (is sorted, sort property, sort dir)
}

عام SortableBindingList<T> يوفر سفرًا أساسيًا قائمًا على الانعكاس:

protected virtual Comparison<T> GetComparer(PropertyDescriptor prop)
{
    return new Comparison<T>(delegate(T x, T y)
    {
        if (prop.GetValue(x) != null)
            return ((IComparable)prop.GetValue(x)).CompareTo(prop.GetValue(y));
        else if (prop.GetValue(y) != null)
            return -1 * ((IComparable)prop.GetValue(y)).CompareTo(prop.GetValue(x));
        else
            return 0;
    });
}

كما ترون، GetComparer() هو افتراضي ، بحيث يمكن للمرء تجاوزه في فئة مشتقة من SortableBindingList<T> من أجل توفير أ كثير مقارن أسرع ، تم تعديله إلى نوع الخاصية التي يتم فرزها بالفعل. على سبيل المثال ، بينما تم فرز المقارن العام (بواسطة أ String خاصية) 10000 سجلات في 4 ثوان ، قامت المقارنة المتخصصة بنفس المهمة في 70 مللي ثانية.

class CustomerList : SortableBindingList<Customer>
{
    protected override Comparison<Customer> GetComparer(PropertyDescriptor prop)
    {
        Comparison<Customer> comparer = null;
        switch (prop.Name)
        {
            case "FirstName":
                comparer = new Comparison<Customer>(delegate(Customer x, Customer y)
                {
                    string xx = (null == x) ? null : x.FirstName;
                    string yy = (null == y) ? null : y.FirstName;
                    return String.Compare(xx, yy);
                });
                break;
            ...
        }
        return comparer;
    }
}

ملاحظة أخيرة: تم نسخ/إلهام الكثير من الكود المنشور من مصادر أخرى ، مثل SO أو Microsoft ، وبالتالي فإن الائتمان ليس لي. كانت مساهمتي الوحيدة هي تشكيل المقارنات الافتراضية ، لكنني متأكد من أن القليل من الغوغل سوف يظهر بشكل أفضل ، وحلول سابقة بناءً على نفس الفكرة.

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