PDA

View Full Version : تراكنش ها در سي شارپ



HDDSoft2001
یک شنبه 29 شهریور 1388, 23:20 عصر
با سلام

دوستان من يه مشكلي داشتم كه نتونستم يه جواب براش پيدا كنم. اون هم كار با تراكنش ها در سي شارپ با بانك اس كيو ال سرور است.
بينيد دوستان ميخاستم ببينم چطوري با تراكنش در ديتا ست و ديتا آداپتور بايد كار كرد و چطوري دستورهاي بعدي را در اين مدت كه هنوز وضعيت تراكنش مشخص نشده را هم انجام داد.

بذاريد اين طور مسئله رو بيان كنم من برنامه نوشتم كه ميخام وقتي كاربر داره يه ركورد رو ويرايش ميكنه ماربر ديگه نتونه فقط ويراش و حذفش كنه. بعد از ذخيره يا انصراف هم به حالت عادي برگرده ركورد.

يك روش اينكه كه از يه فيلد فلگ استفاده كنم كه مقدارش رو موقع ويرايش 1 و 0 كنم يا ... . مشكل : اگه ارتباط به صورت ناگهاني قطع بشه ديگه دردسر داره به خاطر ست نكردن فيلد تگ.
روش ديگر استفاده از همين تراكنش هاست كه فقل بذارم روي ركورد با شرايطي كه گفتم . تو اين روش مديريتش بهتره چون اگه كلاينت ارتباطش قطع شد و اون تگ به حالت مشخص ست نشد ديگه دردسرساز نشه.

حالا ميخام ببينم چطوري بايد اين كارو انجام بدم. منظورم روش دومه.
اگه روش اول بهتره يه سناريوي خوب بگيد.

در ضمن من تونستم با كامند ها اين تراكنش رو انجام بدم ولي محدودم چون قبل از هر چيز بايد اون تراكنش رو كاميت يا رول بك كنم. (چون نميتونم يه سلكت ديگه همون موقع بكنم.)

چطوري اين اعمال رو انجام بدم. خواهش ميكنم يكي جلمع جواب من رو لطف كنه بده. (لطفا با جزئيات مديريت كدش كه چه موقع مثلا بر اثر قفل خطا ميده و ... )


;كد من :


sqlConnection con = new SqlConnection("connection string");
sqlCommand cmd = con.CreateCommand();
cmd.Transaction = con.eginTransaction(IsolationLevel.Serializable);
SqlDataReader rdr = cmd.ExecutedReader();
.
.
.
rdr.Close();

با تشكر

HDDSoft2001
دوشنبه 30 شهریور 1388, 17:56 عصر
با سلام

دوستان واقعا کسی نیست که در این مورد کارکرده باشد. دوستان برنامه نویس ناامیدم نکنید.


با تشکر

moferferi
دوشنبه 30 شهریور 1388, 22:06 عصر
conn.Open();
SqlTransaction sqltrans = conn.BeginTransaction();
try
{
SqlCommand cmdins = new SqlCommand();
cmdins.CommandType = CommandType.StoredProcedure;
cmdins.CommandText = "myTransAction2";
cmdins.Connection = conn;
cmdins.Transaction = sqltrans;
cmdins.Parameters.AddWithValue("@newcustid", textBox1.Text.ToString());
cmdins.Parameters.AddWithValue("@newcompname", textBox2.Text.ToString());
cmdins.Parameters.AddWithValue("@oldcustid", textBox3.Text.ToString());
cmdins.ExecuteNonQuery();
sqltrans.Commit();
MessageBox.Show("comitted");
conn.Close();
filldgv();
//----------------

}
catch (SqlException ex)
{
sqltrans.Rollback();
MessageBox.Show("sql error:\n" + ex.Message, "rollback");
}
catch (Exception ex)
{
MessageBox.Show("system error:\n" + ex.Message, "rollback");
}
finally
{ conn.Close(); }


}

اگه سوال دیگه ای بود در خدمتیم

HDDSoft2001
دوشنبه 30 شهریور 1388, 23:37 عصر
با سلام

خیلی ممنونم از شما دوست عزیز بالاخره یکی تو این زمینه کارکرده بود.

ببینید دوست عزیز کد شما با کد من هیچ فرقی نمی کند فقط شما یک متغیر اضافه تعریف کردید که یکی هست.

خب سوال من اینه که تو همین لحظه قبل از اینکه تراکنش را کامیت یا رولبک کنید یک سلکت انجام بدید. (خطا میدهد چون میگه قبلش باید وضعیت تراکنش را مشخص کنید.)

گیر کار من دقیقا همین جاست.

حالا چه باید کرد دوستان.

با تشکر

Mohsen_Fotouhi
سه شنبه 31 شهریور 1388, 02:35 صبح
سلام دوست عزیز
اگه راستشو بخوای من یک صدم نوشته هات رو بیشتر متوجه نشدم که البته جای شکرش باقیه بهر حال یک مثال ضمیمه کردن شاید بدردت بخوره
موفق باشید

Asad.Safari
سه شنبه 31 شهریور 1388, 12:27 عصر
نیازی به استفاده از کلاس تراکنش در دات نت نیست ... اگر شما در یک کانکشنی باز شده چندین کامند را انجام دهید ... خود به خود اینها داخل یک تراکنش میروند و خود sql server به شما امکان Rollback رو میده ...

moferferi
سه شنبه 31 شهریور 1388, 16:15 عصر
سلام.دوست عزیز من منظور شما را درست متوجه نشدم(اینکه پیغام خطا میده و میگه قبلش وضعیت تراکنش را انتخاب کنید).شما قبل از کامیت کردن هر چندتا دستور و از هر نو که دارید میتونید بزارید.اصلا تراکنش واسه همینه که ضمانت کنه یا همه دستورات به درستی انجام میشه و یا هیچ کدام انجام نشه.اگه میتونه کدت را بزار تا ببینم مشکلش چیه.

HDDSoft2001
سه شنبه 31 شهریور 1388, 16:58 عصر
با سلام


خيلي ممنون از كمك تون. من فهميدم قضيه چي شد با اون مثال كه دوست عزيزم گذاشتن.


مشكل من اين بود كه مثلا وقتي كاربري دارد يك فاكتور را ويرايش (كار مي كند) مي كند آن فاكتور براي ديگر كاربران قفل شود و تا زماني كه آن كاربر با آن فاكتور كار ميكند ديگران حق دسترسي به ان فاكتور را نداشته باشند.

كه من ميخاستم با تراكنش اين مسئله را حل كنم. با خواندن ان فاكتور (ركورد بر اساس شماره فاكتور) و گذاشتن قفل (مثلا قفل آپديت) روي آن ركورد ديگران حق دسترسي به ان را ندارند.

اين روش بهتره چون مديريت ان ساده تر مي باشد.

روشي كه خيلي ها به من پيشنهاد كردم استفاده از يك فيلد فلگ بود كه مثلا وقتي يك كاربر مي خواهد ان فاكتور را بخواند به اون فيلد فلگ نگاه كند اگر 1 (نشان قفل بودن) بود يعني كاربر ديگري در حال كار با آن فاكتور مي باشد در نتيجه كاربر بايد صبر كند تا ان فيلد 0 شود. (قفل برداشته شود) و اگر فيلد فلگ 0 (قفل نبود) بود آن را 1 مي كند (قفل ميكند) و كار ويرايش را شروع مي كند و پس از اتمام ويرايش آن فيلد فلگ را دوباره 0 (قفل را بر مي دارد) مي كند.

اما اين روش مشكلاتي داره مثل اگر ارتباط به صورت ناصحيح قطع بشه اون موقع ديگر اون فيلد فلگ 0 نمي شه در نيجه براي هميشه قفله. (باز يك مكانيزم براي اين مورد لازم كه قفل هاي غير مجاز را بردارد) و يا ممكن است دونفر همزمان بخواهند روي اين فاكتور قفل بذارند و ... .


تراكنش ها رو براي اين ميخاستم. حالا متوجه شديد.


با تشكر

HDDSoft2001
سه شنبه 31 شهریور 1388, 17:19 عصر
با سلام

ببخشيد به دستي دو تا پست گذاشتم چون ميخاستم موضوعات رو قاتي نكنيد. (در اصل براي بالا بردن تعداد پست هام بود. :لبخند: شوخي كردم!)

خب اما خطاي تراكنش ها!

ببنيد من برنامه نويسي رو به صورت سه لايه انجام ميدم و اصا هم از ديتاست و ديتا اداپتور و ... استفاده نمي كنم. من يك كلاس استاتيك نوشتم كه كل دستورات پايگاه داده را به اون پاس ميدم و اكثرا هم به صورت استورپراسيجر هست. و داخل اون كلاس هم از كامند و ديتا ريدر استفاده مي كنم و براي ذخيره اطلاعات خوانده شده هم از ژنريك ها استفاده مي كنم.

مشكل من اين بود زماني كه از تراكنش استفاده مي كردم (مثلا خوانده يك شماره فاكتور و قفل گذاشتن روي ان با همين تراكنش. خب اگه كانكشن رو ببندم يا رول بك يا كاميت كنم قفل برداشته ميشد) و و قبل از رول بك يا كاميت يه دستور ديگه هم با يك كامند ديگه (چون من دستورات رو به اون كلاس استاتيكي كه گفتم پاس ميدادم و اون تو يك كامند ديگه البته با همون كانكشن اجرا مي كرد و خطا مي داد) اجرا ميكردم (مثلا گرفتن ليست مشتريان) و اون خطا رو ميداد.

حالا فهميدم كه همه دستورات رو بايد با همون يك كامندي كه تراكنش داره اجرا كنم و نه با كامند هاي جداگانه.

با تشكر