درست اجرا نشدن یک StoreProcedure در EF

by MDP 8. July 2011 05:59

حتمی برای شما هم اتفاق افتاده که بخشی از محاسبات و یا Logic برنامه رو به پایگاه داده واگذار کنید.مثلا قراره شما تعداد 1 ملیون رکورد که شامل اعداد تصادفی غیر تکراری هست رو به دیتابیس اضافه کنید.

بدترین راه ولی در عوض ساده ترین راه استفاده از یک حلقه For یا هرچیز دیگه ای سمت Client هست.لازم نیست توضیح بدم که این کار یعنی حدود 1 ملیون بار اتصال به پایگاه داده !

راه دوم ، استفاده از StoreProcedure هاست.در این حالت شما دیگه لازم نیست که 1 ملیون بار به پایگاه داده وصل بشید.فقط کافیه که با بار اول اتصال درخواست اجرا شدن اون SP رو باپارامتر های مورد نظر بدید.

همون طوری که میدونید EF به شما اجازه میده علاوه بر Table ها( که به صورت Entity در برنامه Map می شن) SP  و UDF های خودتون هم به EF بدید و خیلی راحت از اونا استفاده کنید.

البته مورد استفاده UDF ها و SP ها و روش معرفی اونها به EF خودش داستانی داره که از بحث الان خارجه !

فرض کنید شما SP مورد نظر ( اضافه کردن 1 ملیون رکورد ) رو نوشتید و به EF معرفی کردید.

شما حتمی مثل من این کار رو انجام میدید :

 

void DoWork()
{
   TestEntities fn = new TestEntities();
   fn.InsertOneMil();
}
 

و اجرا !

برنامه بعد از مدتی متوقف میشه و بدون هیچ خروجی خاصی مبنی بر اتمام کار آماده دریافت فرمان بعدی میشه.مشکل کجاست؟

سادست، EF برای اجرای فرامین مثل Connection های دستی دارای یک Timeout هست(البته این مورد هم مشخصه که EF بر پایه ADO.Net هست، یعنی یک لایه روی Connection و Command ! ). وقتی SP شما درحال اجرا شدن هست،بر اساس قدرت سیستم شما و شرایط دیگه ای مثل : سرت شبکه ( اگه دیتابیس روی شبکه باشه ) و … زمانی رو میگیره که بیشتر از حد معمول EF هست.

برای رفع این مشکل فقط کافیه که به صورت دستی این مقدار رو عوض کنید.

برای تغییر این مقدار دو راه پیش رو دارید :

1 – تغییر تعریف پیشفرض در خود Model

2 – تغییر در مواقع لزوم.

هر روش کارایی خودش رو داره که من هر دو روش رو اینجا میگم.

برای روش اول شما باید Source مدل رو باز کنید و مقدار CommandTimeout رو دستی عوض کنید :

1

حالا فقط کافیه که در Constructors اصلی خود Context مقدار جدید رو اعمال کنید :

 
public TestEntities() : base("name=TestEntities", "TestEntities")
     {
         this.ContextOptions.LazyLoadingEnabled = true;
         this.CommandTimeout = 999999;
         OnContextCreated();
     }
 

این روش وقتی کارایی داره که شما هرکجا که از EF توی برنامتون استفاده می کنید نیاز به Timeout بالا دارید و نمیخواید که هر دفعه این مقدار رو Set کنید.این روش پیشنهاد خوبی نیست.چون خیلی از امکانات رو از دست میدید.

روش دوم منطقی تر از روش اول هست.شما کافیه هرکجا که خواستید یعدر از ساختن یک نمونه از Context مقدار CommantTimeout رو ست کنید:

TestEntities fn = new TestEntities();
fn.CommandTimeout = 999999;

Tags: ,

.Net

My Groups

Poll

از چه پلتفرمی برای توسعه استفاده می کنید



Show Results

Month List