اگر به فایل IocConfig.cs پروژه دقت کرده باشید، مدیریت طول عمر واحد کار به صورت معمولی و متداولی تعریف شده است:
و در اینجا از حالت HybridHttpOrThreadLocalScoped که در برنامههای وب نیز مورد استفاده قرار میگیرد، استفاده نشده است. چرا؟
تعاریف رسمی مرتبط با Thread local و حالت Hypbrid را در اینجا ملاحظه میکنید. در حالت Thread local از یک وهله در طی طول عمر یک ترد استفاده میشود. حالت Hybrid مشخص میکند که اگر برنامه وب بود، از HttpContext برای مدیریت این طول عمر استفاده کن و اگر برنامه دسکتاپ بود از ThreadLocal storage.
خوب، مشکل کجا است؟ در یک برنامه دسکتاپ اگر ترد جدیدی را ایجاد نکنیم، کل برنامه در طول مدتی که در حال اجرا است در یک ترد اصلی اجرا میشود. در نتیجه استفاده از حالت HybridHttpOrThreadLocalScoped در برنامههای دسکتاپ، بسیار شبیه به حالت Singleton است. به این ترتیب با بسته شدن یک پنجره یا هدایت به صفحهای دیگر، Context برنامه و EF رها نخواهند شد (چون تضمین شده است که یک وهله از این شیء در طول عمر ترد جاری وجود داشته باشد). نتیجه آن روبرو شدن با خطاهایی است که ردیابی و دیباگ بسیار مشکلی دارند. برای مثال چندی قبل در سایت مطرح شده بود که چرا در یک برنامه WinForms خطای زیر را دریافت میکنم:
علت پس از چند سؤال جواب، به مدیریت طول عمر UOW مرتبط شد. چون از حالت HybridHttpOrThreadLocalScoped استفاده شده بوده، در صفحهای، شیءایی به Context اضافه شده. پس از مراجعه به صفحهای دیگر، مجددا سعی در اضافه کردن همین شیء گردیده است (با این تصور که با بسته شدن صفحه قبلی، Context هم از بین رفته است). بلافاصله خطای ذکر شده، توسط EF گزارش گردیده است؛ چون هنوز Context باز است و از بین نرفته است.
در برنامههای وب چطور؟
در برنامههای وب، به ازای هر درخواست رسیده، یک ترد جدید ایجاد میشود. به همین جهت استفاده از حالت HybridHttpOrThreadLocalScoped برای داشتن تنها یک Context در طول یک درخواست ضروری است.
نتیجه گیری
در برنامههای دسکتاپ خود اگر از ترد استفاده نمیکنید، از حالت HybridHttpOrThreadLocalScoped برای مدیریت طول عمر UOW استفاده نکنید.
cfg.For<IUnitOfWork>().Use(() => new MyWpfFrameworkContext());
ThreadLocal - A single instance will be created for each requesting thread. Caches the instances with ThreadLocalStorage. Hybrid - Uses HttpContext storage if it exists, otherwise uses ThreadLocal storage
خوب، مشکل کجا است؟ در یک برنامه دسکتاپ اگر ترد جدیدی را ایجاد نکنیم، کل برنامه در طول مدتی که در حال اجرا است در یک ترد اصلی اجرا میشود. در نتیجه استفاده از حالت HybridHttpOrThreadLocalScoped در برنامههای دسکتاپ، بسیار شبیه به حالت Singleton است. به این ترتیب با بسته شدن یک پنجره یا هدایت به صفحهای دیگر، Context برنامه و EF رها نخواهند شد (چون تضمین شده است که یک وهله از این شیء در طول عمر ترد جاری وجود داشته باشد). نتیجه آن روبرو شدن با خطاهایی است که ردیابی و دیباگ بسیار مشکلی دارند. برای مثال چندی قبل در سایت مطرح شده بود که چرا در یک برنامه WinForms خطای زیر را دریافت میکنم:
An object with the same key already exists in the ObjectStateManager
در برنامههای وب چطور؟
در برنامههای وب، به ازای هر درخواست رسیده، یک ترد جدید ایجاد میشود. به همین جهت استفاده از حالت HybridHttpOrThreadLocalScoped برای داشتن تنها یک Context در طول یک درخواست ضروری است.
نتیجه گیری
در برنامههای دسکتاپ خود اگر از ترد استفاده نمیکنید، از حالت HybridHttpOrThreadLocalScoped برای مدیریت طول عمر UOW استفاده نکنید.