PDA

View Full Version : ایجاد تراکنش با استفاده از nested update



hamedgh
یک شنبه 07 مرداد 1386, 14:40 عصر
سلام
دوستان من می خواهم یک تراکنش ایجاد کنم با دو connection مستقل بتوانند تا قبل از زدن

commite بتوانم command هایم را اجرا کنم البته command هایم فقط update هستند

مانند همچین چیزی که اجرا شود

con1 = new SqlConnection("");
con2 = new SqlConnection("")
SqlCommand cmd1 = new SqlCommand("update tel set tel = '123456' where family = 'hamed' ", con1);
SqlCommand cmd2 = new SqlCommand("update tel set tel='456789' where family = 'hamid'", con2);
con1.Open();
con2.Open();
SqlTransaction t1 = con1.BeginTransaction();
cmd1.Transaction = t1;
SqlTransaction t2 = con2.BeginTransaction();
cmd2.Transaction = t2;
cmd1.ExecuteNonQuery();
cmd2.ExecuteNonQuery();

mehdi.mousavi
یک شنبه 07 مرداد 1386, 15:03 عصر
سلام
دوستان من می خواهم یک تراکنش ایجاد کنم با دو connection مستقل بتوانند تا قبل از زدن

commite بتوانم command هایم را اجرا کنم البته command هایم فقط update هستند



سلام.
سوالتون در بخش SQL Server هست، اما کدی که نوشتید C#! اگر منظورتون چگونگی استفاده از transaction ها در SQL هست، باید از BEGIN TRANS و .... استفاده کنید (در Books Online میتونید مطلب کاملشو بخونید). اما اگر میخواهید اینکارو در C# انجام بدین، کافی هستش تا از کلاس جدیدی با نام TransactionScope که در dotNet Framework 2.0 اضافه شده، استفاده کنید:



using (TransactionScope ts = new TransactionScope())
{
SqlConnection con1 = new SqlConnection("");
SqlConnection con2 = new SqlConnection("");

SqlCommand cmd1 = new SqlCommand("update tel set tel = '123456' where family = 'hamed' ", con1);
SqlCommand cmd2 = new SqlCommand("update tel set tel='456789' where family = 'hamid'", con2);

con1.Open();
con2.Open();

cmd1.ExecuteNonQuery();
cmd2.ExecuteNonQuery();

ts.Complete();
}

به این ترتیب هر دو SQL Server خودشون رو در تراکنش enlist می کنن و همه چی طبق انتظارتون انجام خواهد شد. البته به خاطر داشته باشید که اگر TransactionScope متوجه بشه که SQL Server ها local نیستن، اونوقت مجبور میشین تا MSDTC رو هم فعال کنید. البته روشهای دیگه ای هم وجود داره که این روش ساده ترین اونهاست. (برای استفاده از TransactionScope باید System.Transactions.dll رو به reference ها اضافه کنید).

بازم اگر منظورتون رو درست متوجه نشدم، بفرمایید تا توضیح بدم.

hamedgh
یک شنبه 07 مرداد 1386, 16:29 عصر
سلام خیلی ممنون از اینکه جواب فرستادید
من این کار می خواهم در شبکه انجام بدهم یعنی دو نمونه از این برنامه در حال اجرا باشد
و برنامه اول جدول را آپ می کند بدون commite کردن و برنامه دوم می خواهد رکورد دیگری را آپ کند که مشکل پیش می اید و برنامه دوم منتظر می ماند تا جدول commite شود بعد خودش را آپ می کند
البته این کدی که شما نوشتید بدیهی است مهم برای من دو connection مجزا با تراکنش های خاص خودشان است نه در یک تراکنش دو بار آپ کنم مشکل برنامه من دو تراکنشی بودن ان است که تراکنش اول اجازه دیدن رکورد ها را به تراکنش دوم نمی دهد

hamedgh
یک شنبه 07 مرداد 1386, 16:41 عصر
باز هم از شما بخا طر جوابتان ممنون هستم

mehdi.mousavi
یک شنبه 07 مرداد 1386, 17:49 عصر
سلام خیلی ممنون از اینکه جواب فرستادید
من این کار می خواهم در شبکه انجام بدهم یعنی دو نمونه از این برنامه در حال اجرا باشد
و برنامه اول جدول را آپ می کند بدون commite کردن و برنامه دوم می خواهد رکورد دیگری را آپ کند که مشکل پیش می اید و برنامه دوم منتظر می ماند تا جدول commite شود بعد خودش را آپ می کند
البته این کدی که شما نوشتید بدیهی است مهم برای من دو connection مجزا با تراکنش های خاص خودشان است نه در یک تراکنش دو بار آپ کنم مشکل برنامه من دو تراکنشی بودن ان است که تراکنش اول اجازه دیدن رکورد ها را به تراکنش دوم نمی دهد

سلام.
بذارید قبل از اینکه سعی کنم جواب بدم، مطمئن بشم که سوال رو درست متوجه شدم. شما یه برنامه دارید و می خواهید دو instance متفاوت از این برنامه رو در دو سیستم متفاوت اجرا کنید. Instance اول، میره جدول tel رو Update میکنه. Instance دوم می خواد بره یه رکورد دیگه ای رو Update کنه. تا اینجا درست؟

حالا سوال اینه: چه کاری می خواهید Transactional انجام بشه؟ چون کدی که شما نوشتید دو Transaction متمایز از هم ایجاد میکنه که بود و نبودشون فرقی نمیکنه. (چون در واقع در دو تراکنش متفاوت دارید کاری رو انجام میدید).

hamedgh
یک شنبه 07 مرداد 1386, 19:09 عصر
من خواستم برنامه را شبیه سازی کنم که دو تراکنش را با هم نوشتم ولی تراکنش و کامند ها
کانکشن ها هر کدام در برنامه است یعنی هر برنامه یک تراکنش دارد ولی در هرصورت فرقی نمی کند چه در دو برنامه هر کدام یک تراکنش ایجاد شود و یا در یک برنامه د و تراکنش و کانکشن فقط مهم این است که کد بالا اجرا شود یک بار امتحانش کن ببین نتیجه برنامه را و اگر می توانی راه حلی در این زمینه بدون تغییر اساسی در کد نویسی برایم بفرست باز هم از شما ممنون
و نکته دیگر اینکه قرار نیست تراکنش ها کاری انجام بدهند چون به نظر شما کاری بخصو صی انجام نمی دهند و این را دست کم نگریید شاید با کاربردش بعد ها بیشتر اشنا شوید
و من می خواهم اینکار در تراکنش با موفقیت انجام شود


con1 = new SqlConnection("");
con2 = new SqlConnection("")
SqlCommand cmd1 = new SqlCommand("update tel set tel = '123456' where family = 'hamed' ", con1);
SqlCommand cmd2 = new SqlCommand("update tel set tel='456789' where family = 'hamid'", con2);
con1.Open();
con2.Open();
SqlTransaction t1 = con1.BeginTransaction();
cmd1.Transaction = t1;
SqlTransaction t2 = con2.BeginTransaction();
cmd2.Transaction = t2;
cmd1.ExecuteNonQuery();
cmd2.ExecuteNonQuery();

hamedgh
یک شنبه 07 مرداد 1386, 19:13 عصر
و نکته دیگر اینکه قرار نیست تراکنش ها کاری انجام بدهند چون به نظر شما کاری بخصو صی انجام نمی دهند و این را دست کم نگریید شاید با کاربردش بعد ها بیشتر اشنا شوید
و من می خواهم اینکار در تراکنش با موفقیت انجام شود

mehdi.mousavi
یک شنبه 07 مرداد 1386, 19:40 عصر
و نکته دیگر اینکه قرار نیست تراکنش ها کاری انجام بدهند چون به نظر شما کاری بخصو صی انجام نمی دهند و این را دست کم نگریید شاید با کاربردش بعد ها بیشتر اشنا شوید
و من می خواهم اینکار در تراکنش با موفقیت انجام شود

سلام.
کدی که شما نوشتید باعث میشه تا Resource مورد نظر بعد از اجرای اولین ExecuteNonQuery به وضعیت Lock بره. سپس، ExecuteNonQuery دوم باعث میشه تا Lock مورد نظر مجددا گرفته بشه، چون روشی برای مشاهده اینکه Resource در حال حاضر Lock هست یا خیر وجود نداره و تنها روشش این هستش که برای گرفتن lock تلاش بشه. در نتیجه SQL Server میره تا lock رو بگیره، اما چون هنوز lock در اختیار تراکنش اول هست، SQL Server به مدت زمان LOCK_TIMEOUT که بصورت پیش فرض 30 ثانیه هستش صبر میکنه تا بلکه lock آزاد بشه. چون شما Transaction اول رو Commit یا Rollback نکردید، DB Engine هم کاری نمیتونه از پیش ببره و ExecuteNonQuery دوم timeout میشه. این کل واقعه هستش.

چیزی که من حدس زدم از حرفاتون این هستش که میخواهید به این روش Concurrency رو کنترل کنید. اگر هدفتون از این کار کنترل concurrency هستش، روشی که انتخاب کردین صحیح نیست. در غیر اینصورت، بدون Rollback یا Commit کردن Transaction اول Lock آزاد نخواهد شد.

hamedgh
دوشنبه 08 مرداد 1386, 23:32 عصر
سلام
من بخاطر اینکه دیتا بیس را قفل می کرد می خواستم در اینتر نت کسی بهم کمک کند که در این حالت و بدون تغییر ان قفل را باز کرده و عملیات update را انجام دهد این کار برای insert انجام دادم عملی شد ولی برای update نشد اگر را ه حلی برای این بگذارید ممنون می شو م
ولی سعی نکنید که کد نویسی را تغییر دهید
در پناه خدا