PDA

View Full Version : سوال: برگشت عملیات درصورت کامل انجام نشدن قسمت های دیگر



samanff2000
دوشنبه 22 مرداد 1397, 10:46 صبح
با سلام خدمت دوستان
سئوالی که دارم خدمت دوستان مربوط به یک قسمت از برنامه نیست و در بخش های مختلفی کاربرد داره که من به عنوان نمونه یکی دو مورد رو میگم،
1 - فرض کنید در قسمت مشتریان 2 جدول داریم که در یکی اطلاعات مشتریان ثبت میشه و در دیگری درصورتی که کاربری تغییراتی در اطلاعات موجود داده باشه اطلاعات قبلی و جدید درج میشه (لاگ قبل رو نگهداری میکنیم) الان در صورتی که لاگ ثبت بشه و در قسمت بروز رسانی جدول اصلی مشکلی پیش بیاد(بروز رسانی جدول اصلی انجام نشه) میخوام سیستم برگرده و اون رکورد قبلی رو هم ثبت کرده پاک کنه . مورد دیگه ای که میشه بهش اشاره کرد وقتی هست که شما داری سند حسابداری میزنی و از انبار داری کالا کم میکنی در صورتی که کالا خارج بشه و سیستم به خطا بخوره باید برگرده و اون رکورد رو برگشت عملیات بزنه و موارد مشابه اینها رو میشه در بانک ها هم برای برگشت سند ها دید .
2 - همچنین با توجه به اینکه ممکنه کاربر های زیادی بر روی این سیستم کار کنند می خوام زمان ثبت ها سیستم لاک بشه و بعد از انجام یک تراکنش تراکنش بعدی انجام بشه خودم براین کار فکر کردم ار دستور lock برای زمان ثبت استفاده کنم .
لطفا راهنمایی بفرمایید که به چه صورتی این کار رو انجام بدم ممنون

Mahmoud Zaad
دوشنبه 22 مرداد 1397, 11:06 صبح
سلام
باید از transaction استفاده کنید. ترجمه اش میشه همون تراکنش. این (https://msdn.microsoft.com/en-us/library/86773566(v=vs.110).aspx) هم یک نمونه.

samanff2000
دوشنبه 22 مرداد 1397, 12:27 عصر
سلام ممنونم از پاسخ شما
من در این مورد سرچ کردم و مطالب جالبی دستگیرم شد . ممنونم اما تمام مواردی که دیدم با دستورا ADO نوشته شدن . اما من در برنامه از bindingSource و .. استفاده کردم و نمیدونم در اون به چه صورت هست اگرمشکلی نداره من کد رو قرار دادم یک نگاهی بندازید و ببینید در این حالت راهی وجود داره یا باید کل کد هام رو تغییر بدم (با توجه به زیاد بودن فیلد ها و شرط ها فقط چند عدد برای نمونه قرار داده شد و باقی بخش ها هست ). با تشکر

if (MessageBox.Show("آیا میخواهید تغییرات را ذخیره کنید ؟", "اطلاع", MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
{
///ثبت در جدول تغییرات
r2 = forushgahjadidDataSet.moshtari_tarikhche.NewRow();
r2["fname_old"] = r["fname"];
r2["idmoshtari"] = r["idmoshtari"];
r2["sharh_new"] = txt_sharh.Text.Trim();

///ثبت در جدول اصلی
r["fname"] = txt_fname.Text.Trim();
r["lname"] = txt_lname.Text.Trim();
r["idmeli"] = txt_idmeli.UnmaskedText.ToString();
r["addres1"] = txt_addres.Text.Trim();

lock (thisLock)
{
forushgahjadidDataSet.moshtari_tarikhche.Rows.Add( r2);
moshtari_tarikhcheTableAdapter.Update(forushgahjad idDataSet.moshtari_tarikhche);


moshtariTableAdapter.Update(forushgahjadidDataSet. moshtari);

r2 = null;
r = null;
}

}

Mahmoud Zaad
دوشنبه 22 مرداد 1397, 14:33 عصر
من از bindingSource استفاده نمی کنم و آشنایی خاصی هم باهاش ندارم ولی در جستجو این لینک (https://msdn.microsoft.com/en-us/library/ms233770.aspx) رو پیدا کردم، شاید مفید باشه.

samanff2000
دوشنبه 22 مرداد 1397, 15:38 عصر
سلام ممنونم از لطفتون
من این لینک رو پیدا کردم و اومدم کدم رو هم شبیه این درست کنم اما خطا داره . نمیدونم باید چه تغییری بدم .

this.Validate();
this.bindingSource1.EndEdit();
this.bindingSource2.EndEdit();

using (System.Transactions.TransactionScope moshtariTransaction =
new System.Transactions.TransactionScope())
{
testOrders();

moshtariTransaction.Complete();
forushgahjadidDataSet.AcceptChanges();
}

private void testOrders()
{forushgahjadidDataSet.moshtariDataTable mm;
mm = (forushgahjadidDataSet.moshtariDataTable)forushgah jadidDataSet.moshtari.GetChanges();
NorthwindDataSet.OrdersDataTable deletedOrders;
deletedOrders = (NorthwindDataSet.OrdersDataTable)
northwindDataSet.Orders.GetChanges(DataRowState.De leted);

if (mm != null)
{
try
{
//ordersTableAdapter.Update(deletedOrders);
moshtariTableAdapter.Update(forushgahjadidDataSet. moshtari);
}
catch (System.Exception ex)
{
MessageBox.Show("DeleteOrders Failed");
}
}
}
دوستان اگه ممکنه یه کمکی کنید ممنون میشم

Mahmoud.Afrad
دوشنبه 22 مرداد 1397, 19:31 عصر
https://stackoverflow.com/q/6039383

samanff2000
سه شنبه 23 مرداد 1397, 09:13 صبح
سلام دوستان ممنون از توجه و پاسخگویی شما عزیزان
من کدم رو تغییر دادم که در انتها مشاهده میکنید اما برای تست کار های انجام شده در قسمت try کانکشن رو بستم تا رول بک انجام بشه اما متاسفانه با خطا روبرو شد که تصویر خطا رو هم فرستادم . من فکر کردم شاید برای اینه که commit شده به همین دلیل اومدم قسمت commit هارو به finally بردم که شاید این مشکل رفع بشه اما باز هم در زمان برگشت با همون خطای قبلی روبرو شدم و در هرد حالت رکورد جدید در جدول تاریخچه اضافه شده و برگشت داده نشد . ممنون میشم اگر لططفا راهنمایی بفرمایید . با تشکر
تصویر خطا:
148697

کد برنامه در حالت اول :

moshtariTableAdapter.Connection.Open();
moshtari_tarikhcheTableAdapter.Connection.Open();

moshtariTableAdapter.Transaction = moshtariTableAdapter.Connection.BeginTransaction() ;
moshtari_tarikhcheTableAdapter.Transaction = moshtari_tarikhcheTableAdapter.Connection.BeginTra nsaction();

forushgahjadidDataSet.moshtari_tarikhche.Rows.Add( r2);
try
{
lock (thisLock)
{
moshtari_tarikhcheTableAdapter.Update(forushgahjad idDataSet.moshtari_tarikhche);

moshtariTableAdapter.Update(forushgahjadidDataSet. moshtari);
moshtari_tarikhcheTableAdapter.Transaction.Commit( );

moshtariTableAdapter.Connection.Close();

moshtariTableAdapter.Transaction.Commit();
}
}
catch
{
moshtariTableAdapter.Transaction.Rollback();
moshtari_tarikhcheTableAdapter.Transaction.Rollbac k();
}
finally
{
moshtariTableAdapter.Connection.Close();
moshtari_tarikhcheTableAdapter.Connection.Close();
r2 = null;
r = null;
}

jafarpalideh
سه شنبه 23 مرداد 1397, 11:37 صبح
کدت رو اینطوری تغییر بده .



try
{
TransactionScope ts = new TransactionScope()


lock (thisLock)
{
moshtari_tarikhcheTableAdapter.Update(forushgahjad idDataSet.moshtari_tarikhche);

moshtariTableAdapter.Update(forushgahjadidDataSet. moshtari);



moshtariTableAdapter.Connection.Close();



}
ts.Complete();


}

}

samanff2000
سه شنبه 23 مرداد 1397, 12:41 عصر
سلام ممنونم از پاسخ شما
من کد هارو به روشی که فرمودید تغییر دادم و commit رو هم در همین قسمت lock آوردم اما متاسفانه باز هم بعد از اجرا پیام خطا برای برگشت تاریخچه میده و نمیتونه اون رو برگردونه همچنین با بررسی خط به خط دیدم که بعد از اینکه اومد کانکشن رو بستم (برای ایجاد خطا) باز هم داره ادامه کار رو انجام میده تا پایان و فقط ts.Complete اجرا نمیشه و بعد به catch میره و با خطا روبرو میشه :گریه::گریه::گریه:
148699

moshtariTableAdapter.Connection.Open();
moshtari_tarikhcheTableAdapter.Connection.Open();
moshtariTableAdapter.Transaction = moshtariTableAdapter.Connection.BeginTransaction() ;
moshtari_tarikhcheTableAdapter.Transaction = moshtari_tarikhcheTableAdapter.Connection.BeginTra nsaction();
forushgahjadidDataSet.moshtari_tarikhche.Rows.Add( r2);
try
{
TransactionScope ts = new TransactionScope();

lock (thisLock)
{
moshtari_tarikhcheTableAdapter.Update(forushgahjad idDataSet.moshtari_tarikhche);
moshtariTableAdapter.Connection.Close();
moshtariTableAdapter.Update(forushgahjadidDataSet. moshtari);
moshtari_tarikhcheTableAdapter.Transaction.Commit( );
moshtariTableAdapter.Transaction.Commit();
}
ts.Complete();
}
catch
{
moshtariTableAdapter.Transaction.Rollback();
moshtari_tarikhcheTableAdapter.Transaction.Rollbac k();
}
finally
{
moshtariTableAdapter.Connection.Close();
moshtari_tarikhcheTableAdapter.Connection.Close();
r2 = null;
r = null;
}

jafarpalideh
سه شنبه 23 مرداد 1397, 12:47 عصر
اونارو بردار.

moshtariTableAdapter.Transaction.Rollback();
moshtari_tarikhcheTableAdapter.Transaction.Rollbac k();

samanff2000
سه شنبه 23 مرداد 1397, 13:51 عصر
سلام ممنونم بابت پاسخ شما
این تکه کد رو هم اجرا کردم اما باز هم مشکل داره : جدول اول رو آپدیت میکنه و جدول دوم رو هیچ تغییری نمیده و برگشت هم نمیشه و یه مشکل دیگه ای هم که داره اینه که وقتی این دستور اجرا میشه در صفحه دیگه ای دارم جدول رو بروز میکنم که اونجا هم خطا میگیره

this.moshtariTableAdapter.Fill(this.forushgahjadid DataSet.moshtari);

148700

Mahmoud.Afrad
سه شنبه 23 مرداد 1397, 21:48 عصر
کانکشن نباید قبل از commit بسته بشه. در finally کانکشن و تراکنش را از بین ببرید.
همه Adapter ها باید از یک کانکشن و تراکنش مشترک استفاده کنند.
نیازی به TransactionScope نیست
نیازی به lock نیست. در مورد جلوگیری از همزمانی در آپدیت دیتابیسس جستجو کنید.