لماذا من الممكن تعداد استعلام DBLINQ بعد استدعاء Dispose () على datacontext؟

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

  •  27-09-2019
  •  | 
  •  

سؤال

تحديث - يبدو أن الإجابة هي أن DBLINQ لا تنفذ Dispose() بصورة صحيحة. دو!


فيما يلي كل نوع من أنواع المضللة - النتيجة النهائية: DBLINQ لا تعادل (حتى الآن) LINQTOSQL ، كما افترضت عندما طرحت هذا السؤال في الأصل. استخدامه بحذر!

أنا أستخدم نمط المستودع مع DBLINQ. تنفيذ كائنات المستودع الخاص بي IDisposable, ، و ال Dispose() الطريقة تفعل الشيء فقط- Dispose() على ال DataContext. كلما استخدمت مستودعًا ، ألفه في using كتلة ، مثل هذا:

public IEnumerable<Person> SelectPersons()
{
    using (var repository = _repositorySource.GetPersonRepository())
    {
        return repository.GetAll(); // returns DataContext.Person as an IQueryable<Person>
    }
}

هذه الطريقة تُرجع IEnumerable<Person>, ، لذلك إذا كان فهمي صحيحًا ، فلن يحدث أي استفسار عن قاعدة البيانات فعليًا حتى Enumerable<Person> يتم اجتيازه (على سبيل المثال ، عن طريق تحويله إلى قائمة أو صفيف أو باستخدامها في أ foreach حلقة) ، كما في هذا المثال:

var persons = gateway.SelectPersons();
// Dispose() is fired here
var personViewModels = (
    from b in persons
    select new PersonViewModel
    {
        Id = b.Id,
        Name = b.Name,
        Age = b.Age,
        OrdersCount = b.Order.Count()
    }).ToList(); // executes queries

في هذا المثال، Dispose() يتم استدعاؤه مباشرة بعد الإعداد persons, وهو أمر IEnumerable<Person>, ، وهذه هي المرة الوحيدة التي يتم فيها تسمى.

لذلك ، ثلاثة أسئلة:

  1. كيف يعمل هذا؟ كيف يمكن التخلص DataContext لا يزال الاستعلام عن قاعدة البيانات للحصول على النتائج بعد DataContext تم التخلص منه؟
  2. ماذا فعلت Dispose() في الواقع؟
  3. سمعت أنه ليس ضروريًا (على سبيل المثال ، انظر هذا السؤال) للتخلص من أ DataContext, ، لكن انطباعي كان أنها ليست فكرة سيئة. هل هناك أي سبب ليس للتخلص من dblinq DataContext?
هل كانت مفيدة؟

المحلول

1 كيف يعمل هذا؟ كيف يمكن ل datacontext التخلص أن يستمر في الاستعلام عن قاعدة البيانات للحصول على النتائج بعد التخلص من datacontext؟

هو - هي لا الشغل. هناك شيء لا تعرضه لنا. أظن أن فئة المستودع الخاصة بك لا تتخلص من DataContext بشكل صحيح/في الوقت المناسب ، أو أنك تكتب بشكل ملحوظ ToList() في نهاية كل استعلام ، والذي ينفي تمامًا تحول الاستعلام والتنفيذ المؤجل الذي تحصل عليه عادة.

جرب الرمز التالي في تطبيق اختبار ، أنا ضمان أنت سوف ترمي ObjectDisposedException:

// Bad code; do not use, will throw exception.
IEnumerable<Person> people;
using (var context = new TestDataContext())
{
    people = context.Person;
}
foreach (Person p in people)
{
    Console.WriteLine(p.ID);
}

هذه هي أبسط حالة ممكنة استنساخ ، وسوف ترمي دائمًا. من ناحية أخرى ، إذا كتبت people = context.Person.ToList() بدلاً من ذلك ، تم بالفعل تعداد نتائج الاستعلام داخل ال using الحظر ، الذي سأراهن عليه هو ما يحدث في قضيتك.

2 ماذا تفعل () في الواقع؟

من بين أشياء أخرى ، يضع علامة تشير إلى أن DataContext يتم التخلص منه ، والذي يتم فحصه في كل استعلام لاحق ويسبب DataContext لرمي ObjectDisposedException مع الرسالة Object name: 'DataContext accessed after Dispose.'.

كما أنه يغلق الاتصال ، إذا كان DataContext فتحها وتركها مفتوحة.

3 سمعت أنه ليس من الضروري (على سبيل المثال ، انظر هذا السؤال) التخلص من datacontext ، لكن انطباعي كان أنها ليست فكرة سيئة. هل هناك أي سبب لعدم التخلص من datacontext LINQTOSQL؟

هو - هي هو ضروري ل Dispose ال DataContext, ، كما هو ضروري Dispose كل شيء آخر IDisposable. يمكن أن تتسرب من الاتصالات إذا فشلت في التخلص من DataContext. يمكنك أيضًا تسرب الذاكرة إذا تم استرداد أي من الكيانات من DataContext يتم الاحتفاظ بها على قيد الحياة ، لأن السياق يحافظ على ذاكرة التخزين المؤقت للهوية الداخلية لنمط وحدة العمل الذي تنفذه. ولكن حتى لو لم يكن أي من هذا هو الحال ، إنه ليس قلقك ماذا Dispose الطريقة تفعل داخليا. افترض أنه يفعل شيئًا مهمًا.

IDisposable هو عقد هذا يقول ، "قد لا يكون التنظيف تلقائيًا ؛ فأنت بحاجة إلى التخلص مني عند الانتهاء." ليس لديك أي ضمانات لما إذا كان للكائن مع نهائيات نهائية خاصة به ينظف بعدك إذا نسيت ذلك Dispose. تخضع التطبيقات للتغيير ، وهذا هو السبب في أنه ليس من الجيد الاعتماد على السلوك المرصود بدلاً من المواصفات الصريحة.

أسوأ شيء يمكن أن يحدث إذا تخلصت من IDisposable مع فارغة Dispose الطريقة هي أنك تضيع بعض دورات وحدة المعالجة المركزية. أسوأ شيء يمكن أن يحدث إذا كنت يفشل للتخلص من IDisposable مع التنفيذ غير التافهة هذا هو أنك تسرب الموارد. الاختيار هنا واضح ؛ إذا رأيت IDisposable, ، لا تنسى التخلص منه.

نصائح أخرى

"الأشخاص" عبارة عن مجموعة غير قابلة للتطبيق ، لا يلزم سوى datacontext (مستودع) إجراء مكالمة .getNew.

الكلمات الرئيسية من/select/etc هي السكر النحوي لطرق التمديد المضافة في مساحة الاسم. تضيف طرق التمديد هذه الوظيفة التي تستخدمها في استعلامك ، وليس DataContext. في الواقع ، يمكنك القيام بكل هذا دون استخدام LINQ2SQL على الإطلاق ، عن طريق إنشاء برمجي لإظهار.

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

ستحتوي مجموعة iEnumerable على جميع السجلات من مستودعك ، ولهذا السبب لا تتطلب DataContext لإجراء الاستعلام.

طرق التمديد: http://msdn.microsoft.com/en-us/library/bb383977.aspx

طرق تمديد LINQ:http://msdn.microsoft.com/en-us/library/system.linq.enumerable_members.aspx

في أعماق واجهة برمجة التطبيقات ، من المحتمل أن ترى طريقة باستخدام واجهة برمجة التطبيقات مثل هذه:

http://msdn.microsoft.com/en-us/library/y6wy5a0f(v=vs.100).aspx

عند تنفيذ الأمر ، يتم إغلاق كائن الاتصال المرتبط به عند إغلاق كائن DataReader المرتبط به.

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