PDA

View Full Version : Exception Handling



shotshat
یک شنبه 21 مرداد 1386, 20:58 عصر
میتونید یه خورده راجع به کار با Exception handling توضیح بدید؟
توی برنامه ای که کاربر دو تا اسم در textbox وارد می کند و اسمها در تیبلمون در sql ذخیره میشه میخوام وقتی کاربر واسه یکی از اسمها که کلید اصلی است اسم تکراری میده و سیستم ارور میده، یه جوری به کاربر خبر بدم که اسمت تکراری است.چه جوری باید try/catch اش رو بنویسم؟

MH2538
یک شنبه 21 مرداد 1386, 21:45 عصر
سلام
دوست عزیز
errorhandling برای هر بخش , بستگی زیادی به قوانین همون بخش داره.
مثلاً همین نمونه KeyViolation,برای مثال وقتی چنین اتاقی میافته از طرف دیتابیس به برنامه و از برنامه به errorhandler پیامی ارسال میشه که مثلاً کد خطای دیتابیس توی اون قرار داره.
در حالت کلی و برای برنامه های بزرگ , بنا به دلایل خیلی زیاد (مثلاً قابلیت Multilanguage بودن ظرح خطا) یک جدول از خطاهای متداول و یک شرح قابل فهم معادل برای کاربر در نظر می گیرند.
مثلاً اگه دیتابیش خطای ORA-19660 بده کد ORA-19660 به اون جدول فرستاده شده و معادل قابل درک اون رو برای کاربر ارسال می کنند.
اگر یک نمونه عملی خواستی اطلاع بده تا برات همینجا بگذارم

shotshat
یک شنبه 21 مرداد 1386, 21:55 عصر
اگر برای نمونه همون مثالی رو که بالا گفتم بنویسید ممنون میشم.

من چند تا مثال از try/catch دیدم ولی نفهمیدم توی پرانتز جلوی catch چی باید بنویسیم؟ اسم خطا رو؟!

hdv212
یک شنبه 21 مرداد 1386, 22:13 عصر
shotshat جان میتونی برای جلوگیری از ورود اطلاعات تکراری، قبل از وارد کردن اطلاعات که باعث رویداد استثنا میشه، ابتدا یه query به دیتابیس بزنی و چک کنی که اون رکورد با مشخصاتی که کاربر وارد کرده وجود داره یا نه، بعد عمل insrt یا update رو انجام بدی.

PC2st
یک شنبه 21 مرداد 1386, 22:55 عصر
من چند تا مثال از try/catch دیدم ولی نفهمیدم توی پرانتز جلوی catch چی باید بنویسیم؟ اسم خطا رو؟!
در پرانتز بعد از کلمه catch باید نوع خطا مشخص بشه.

MH2538
دوشنبه 22 مرداد 1386, 07:19 صبح
سلام
یک نمونه کد واقعی با کدخطاهای غیرواقعی اوراکل برات میذارم ببینی تا متوجه شی دقیقاً در زمان رخداد خطا چه اتفاقی می افته.
ضمناً دو تا تابع MailToNetworkAdmin و LogIt توابعی که من خودم توی پروژه ام نوشتم و جزو دستورات#C نیست


try
{
OraCnt.Open();
}
catch (OracleException OEx)
{
if (OEx.Code=="10660")
MessageBox.Show("پیغام متناظر با این خطا نمایش داده شود");
else
if (OEx.Code=="10661")
{
LogIt(OEx);
MessageBox.Show("پیغام متناظر با این خطا نمایش داده شود و در لیست خطاها نگهداری شود تا بعداً رسیدگی شود");

}
else
if (OEx.Code == "10662")
{
MailToNetworkAdmin("خطا در اتصال به شبکه");
//سریعاً به مسئول شبکه ایمیل زده شود.
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

shotshat
دوشنبه 22 مرداد 1386, 10:42 صبح
جناب MH2538 من چند تا مثال قبلا خودم دیده بودم و همون طوری که گفتم مشکلم اینه که جلوی Catch چی باید بنویسیم و در مثال شما هم این مشکل کماکان واسم حل نشده مونده . من نوع خطا رو از کجا باید بفهمم ؟

MH2538
دوشنبه 22 مرداد 1386, 10:53 صبح
سلام
دوست خوبم اینکه شما چه چیزی باید بنویسید به این بر می گردد که انتظار چه خطاهایی را دارید.
مثلاً اگر قرار است کاربر دو عدد را بر هم تقسیم کند شما باید انتظار خطای Divded By Zero یعنی تقسیم بر صفر را داشته باشید.(البته شما باید پیش بینی این را بکنید و قبل از انجام تقسیم کنترا کنید که کاربر صفر وارد نکرده باشد)
مثال بالا یک مثال ححیلی ساده بود.
نمونه کاربردی تر که خیلی هم رایج است،‌جلوگیری از واردکردن کلید تکراری به جدول است زیرا این کار باعث نمایش خطای پیام KeyViolation خواهد شد.
واضح است در این حالت شما منتظر پیام هایی از جنس دیتابیس خواهید بود و به ازاء نمایش پیام خطای فوق شما به کاربر اعلام می کنید که کلید تکراری واورد کرده است یا شاید یک پیغام مناسب تر بدهید.
کسی انتظار ندارد شما همه خطاها را در همان مرحله اول پیش بینی کنید بنابراین در بخش Handler پیام خطاهایی که شما حدس می زنید بوجود بیاید را Handle می کنید.
بخش دیگری از این خطاها در زمان تست برنامه پیدا می شوند و شما هم پیام قابل فهم معادل آن را برای کاربر نمایش می دهید.
یا مثلاً‌وقتی من با اوراکل کار می کنم و دستور اوراکل را اجرا می کنم مسلماً یک دسته از خطاهای من مربوط به خود پیام های خطای اوراکل خواهد بود پس من OracleException تعریف می کنم.
ضمناً در مورد ErrorHandling تا دست به کار نشی و برنامه ننویسی،‌درک عملی اون یه کم مشکل خواهد بود،‌پس شروع کن.

اگر باز هم نقطه نامفهومی بود من در خدمتم.

shotshat
دوشنبه 22 مرداد 1386, 11:20 صبح
جناب hdv212 راستش رو بخوای من خودم اولش همین کاری رو که شما میگید خواستم بکنم ولی گفتم اگر توی یک فرم چند تا storedProcidure بخواد اجرا بشه (یکی واسه Insert یکی واسه چک کردن) پس حتما باید تمام دستورات اتصال به پایگاه داده هم 2 بار نوشته بشه(درسته؟!) و کلی برنامه طولانی میشه، پس حالاکه C# زحمت می کشه واسه فیلد های تکراری ارور میده منم یه خورده زحمت بکشم یاد بگیرم Catch اش کنم تمومه!

hdv212
دوشنبه 22 مرداد 1386, 13:19 عصر
shotshat جان برای این کار لازم نیست، دستورات مشترک توی همه ی command ها رو دوباره بنویسی، مثل connectionString، کافیه که اونا رو public تعریف کنی تا توی کل فرمت قابل دسترس باشه و دیگه نخوای توی هر قسمت، یه آبجکت دیگه ازش بسازی، برای سوال دومت در مورد اینکه جلوی catch چی بنویسی، شما در حقیقت توی برنامه مشخص میکنی، هر وقت استثنایی از نوع جلوی کلمه ی catch اتفاق افتاد، مجموعه دستورات بلوک catch رو اجرا کن، با این کار exception ای که اتفاق میفته رو handle یا مدیریت کردی.

sm_ezadpanah
دوشنبه 22 مرداد 1386, 13:26 عصر
با سلام دوست عزیز این که کاری نداری برای درج اول یک سلکت بگیر اگه خروجی دیتاست صفربود درج کن در غیر این صورت داخل یه message box اینو به کابرت بگو

shotshat
دوشنبه 22 مرداد 1386, 14:09 عصر
با تشکر از دوستان عزیز ، مثال بالا رو نوشتم وکار هم کرد. کار سختی نیست ولی این که نوع استثنا رو بدونیم چیه یک کم احتیاج به تجربه داره.

shotshat
دوشنبه 22 مرداد 1386, 14:11 عصر
hdv212 جان فکر کنم فقط connectionString رو بشه مشترک استفاده کرد وبقیه رو (,...SqlCommand,SqlDataReader) باید جدا تعریف کرد. حالا من دارم سعی می کنم یه کلاس بنویسم که دستورات اتصال به دیتا بیس رو بذارم توش که واسه هر فرم مجبور نشم همش رو بنویسم اما از اونجایی که توی C# خیلی مهارت دارم، حسابی گیر کردم.

shotshat
دوشنبه 22 مرداد 1386, 14:49 عصر
جناب ایزدپناه میشه کدشو بگید چه جوریه؟

sm_ezadpanah
پنج شنبه 25 مرداد 1386, 10:58 صبح
باسلام
دوست عزیز اینم کدش :
ds.Clear();

con = new SqlConnection(constr);
da = new SqlDataAdapter("Select * from activities where id='"+textBox1.Text+"'",con);
da.Fill(ds,"vmem");
dataGrid1.DataSource = ds;
dataGrid1.DataMember = "vmem";
int check=ds.Tables["vmem"].Rows.Count;
if (check == 0)
{
"اینجا اون دستور درج یا هرچی که می خوای بنویس"


}
else {
MessageBox.Show("کاربر محترم شماره انتخابی شما هم اکنون موجود است لطفا آنرا تغییر دهید");
}
تو این دستورات من اومدم یه سلکت از جدولم گرفتم بعد گفتم اگه رکوردی با این شماره id وجود نداشت حالا مثلا با او شماره id درج کن یا هرچیزی . اگر با اون شماره بود یه پیام بده به کاربر تا شماره رو عوض کن
مفق باشید

sm_ezadpanah
پنج شنبه 25 مرداد 1386, 11:00 صبح
راستی او constr هم منظور همون رشته اتصال به بانکه

sm_ezadpanah
پنج شنبه 25 مرداد 1386, 11:08 صبح
راستی او constr هم منظور همون رشته اتصال به بانکه

safura
سه شنبه 30 مرداد 1386, 13:39 عصر
این کلاس رو یکی از دوستان نوشته و خیلی خوب توضیح داده که مشکل من هم حل شد
از این مسیر می تونی ببینی:
http://barnamenevis.org/forum/showthread.php?t=76165&highlight=clsConnection

hdv212
سه شنبه 30 مرداد 1386, 15:50 عصر
hdv212 جان فکر کنم فقط connectionString رو بشه مشترک استفاده کرد وبقیه رو (,...SqlCommand,SqlDataReader) باید جدا تعریف کرد.
شما میتونی بدون اینکه جداگانه تعریف کنی، فقط بهشون مقدار بدی این خیلی راحت تره تا اینکه هر کجا که رسیدی که آبجکت بسازی.