View Full Version : فیلد یکتا در برنامه تحت شبکه
Developer Programmer
جمعه 09 فروردین 1387, 11:59 صبح
فرض کنید یه برنامه داریم که قراره فاکتور رو محاسبه و چاپ کنه
برای اینکار :
یه جدول در نظر گرفتیم که میگه فاکتور شماره فلان(کلید اصلی) مال چه شرکتیه و در چه تاریخی و...
جدول دومی هم داریم که ریز فاکتور رو بیان میکنه... یعنی فاکتور شماره فلان(کلید خارجی)، از چه جنسی و به چه تعداد و به چه قیمتی و...
روش کارمون اینه که کاربر روی دگمه "صدور فاکتور جدید" کلیک میکنه و یه شماره فاکتور دریافت میکنه (برنامه با (Select Max(id یه شماره اختصاص میده) و بعد میاد و ریز فاکتورها رو می نویسه و در نهایت دگمه "ثبت فاکتور" رو کلیک میکنه و برنامه داده های لازم رو توی دو جدول درج میکنه
مشکل اینجاست که در فاصله ای که کاربر مشغول تایپ فاکتوره... کاربر دیگه میتونه بیاد و شماره دیگه ای با اون نام رو ثبت کنه.
ضمن اینکه میخوام بدونم آخرین شماره فاکتوری که هرکاربر وارد کرده، چه شماره ای بوده
Amir_Safideh
جمعه 09 فروردین 1387, 15:34 عصر
خوب چیزی که به ذهن من میرسه اینه که شما دو کار میتونید بکنید .
1 - بعد از اینکه کاربر دکمه ثبت فاکتور رو زد ابتدا با یه کوئری چک کنید که شماره فاکتور مورد نظر در دیتابیس هست یا نه اگر بود با یک try except end از ثبت فاکتور جلوگیری کنید . که این روش خیلی جالب نیست چون کاربر ممکنه که شماره فاکتور رو چندین جا ثبت کرده باشه و حالا دوباره مجبور به تصحیح اونها بشه .
2 - در این روش زمانی که کاربر دکمه صدور فاکتور جدید رو زد فاکتور واقعا در دیتابیس ایجاد و ذخیره بشه و شماره فاکتور واقعی رو به کاربر بده و دراین حین اگر کاربر بعدی وارد شد برای اون هم همین مراحل انجام میشه . خوب در اینصورت هیچوقت شماره فاکتور تکراری نمیشه و اگر احیانا کاربر هم از ذخیره اطلاعات منصرف شد میتونید فاکتور ایجاد شده رو حذف کنید .
----------
موفق باشید .
Developer Programmer
جمعه 09 فروردین 1387, 17:40 عصر
در این روش زمانی که کاربر دکمه صدور فاکتور جدید رو زد فاکتور واقعا در دیتابیس ایجاد و ذخیره بشه و شماره فاکتور واقعی رو به کاربر بدهباز هم نمی شه به طور قطع گفت... چون زمانی که برنامه داره با Select Max شماره رو بدست میاره تا Insert کنه،کاربر دیگه میتونه رکورد Insert کنه.
(طبق طرح طراح سیستم ، باید کلید اصلی رو برنامه حساب کنه)
vcldeveloper
جمعه 09 فروردین 1387, 18:26 عصر
بهتر هست که خود بانک مقدار کلید رو مشخص کنه (با استفاده از فیلد Auto Increment ). برای اینکه در زمان تایپ ریزفاکتور کلید مربوط به فاکتور به فاکتور دیگه ایی اختصاص پیدا نکنه، می تونید رکورد مربوط به فاکتور رو در جدول فاکتور ایجاد کنید. یعنی همین که کاربر "صدور فاکتور" رو اجرا میکنه، یک رکورد به جدول فاکتورها اضافه بشه و مقدار فیلد ID اش برگشت داده بشه. حالا کاربر میتونه مقادیر ریز فاکتور رو تایپ کنه. برای هر رکورد از ریزفاکتور هم مقدار ID فاکتور به صورت کلید خارجی درج میشه. البته رکوردها به جدول مربوطه ارسال نمیشند، بلکه از Batch Update استفاده میشه؛ یعنی وقتی کاربر "ثبت فاکتور" رو اجرا میکنه، ریزفاکتورها به جدول مربوطه ارسال میشند. به این ترتیب اگر کاربر قبل از ثبت فاکتور منصرف شد، رکوردی از جدول ریزفاکتورها پاک نمیشه، فقط یک رکورد از جدول فاکتورها که ایجاد شده بود، حذف میشه.
تنها مشکلی که ممکن هست بوجود بیاد اینه که اگر در حین ورود ریزفاکتورها مشکلی بوجود بیاد، مثلا برق بره، رکورد مربوط به فاکتور بدون اینکه حذف بشه، در بانک باقی میمونه. برای رفع این مشکل میشه از Transaction استفاده کرد، ولی چون در مراحل ذکر شده تایپ محتوی توسط کاربر وجود داره، این کار میتونه Performance بانک رو بشدت کاهش بده و برای سایر کاربران هم مشکل ایجاد کنه. راه دیگه اینه که برنامه هر بار که اجرا میشه، مقداری رو در فایلی یا رجیستری ثبت کنه و در لحظه ایی که میخواد بسته بشه، اون مقدار رو حذف کنه. اگر دفعه بعدی که برنامه اجرا شد اون مقدار هنوز موجود بود، یعنی برنامه به شکل غیرمتعارفی بسته شده (مثلا هنگ کرده، یا برق رفته). در این صورت میشه روتینی رو اجرا کرد که چک کنه آیا رکوردی از جدول فاکتورها هست که به هیچ رکوردی در جدول ریزفاکتورها متصل نباشه، یا نه. اگر همچین رکوردی وجود داشت، این رکورد حذف بشه.
Developer Programmer
جمعه 09 فروردین 1387, 19:30 عصر
یعنی همین که کاربر "صدور فاکتور" رو اجرا میکنه، یک رکورد به جدول فاکتورها اضافه بشه و مقدار فیلد ID اش برگشت داده بشهخوب اگه فیلد Auto Increment نباشه؛ بنظرت چطوره قبل از Insert ،در قالب یه تراکنش، جدول رو Lock کنیم و بعد از Insert جدول رو Unlock کنیم ؟ (منتها نمی دونم نوع قفل رو چی انتخاب کنم و اینکه واقعا تراکنش لازمه یا نه!)
bad_boy_2007
شنبه 10 فروردین 1387, 00:31 صبح
خوب اگه فیلد Auto Increment نباشه؛ بنظرت چطوره قبل از Insert ،در قالب یه تراکنش، جدول رو Lock کنیم و بعد از Insert جدول رو Unlock کنیم ؟ (منتها نمی دونم نوع قفل رو چی انتخاب کنم و اینکه واقعا تراکنش لازمه یا نه!)
همون راه دومی رو که آقای کشاورز گفتند بسیار خوبه و مشکلت رو رفع میکنه
ببین دوست من کد شما باید مشابه کد زیر باشه :
تراکنش جدید را شروع کن
فاکتور را ثبت کن
شماره فاکتور ثبت شده را بگیر (با استفاده از دستور SCOPE_IDENTITY() یا Select کردن MAx(ID))
اقلام فاکتور را با شماره ای که از دستور فوق بدست آورده ای ثبت کن
تراکنش را Commit کن
فقط یک موردی رو که یادم رفت بگم اینه که این اعمال رو زمانی انجام بده که کاربر کلید ثبت رو زد نه اینکه در لود فرم تراکنش رو شروع و در Close فرم تراکنش رو Commit کنی که این عمل گذشته از اینکه ممکنه باعث Timeout شدن تراکنش میشه ، باعث میشه که کاربران دیگه حق نوشتن در جدول فوق را نداشته باشند .
و یک پردازش استثنا بزار که اگه به Exception بر خوردی تراکنش رو Rollback کنه
حالا اون مشکلی که شما در مورد احتمال وقوعش صحبت کردی که ممکنه دو کاربر همزمان فاکتور رو ثبت کنن ، اگر همزمان این عمل انجام بشه که احتمالش در حد صفر هست چون با تراکنش کارت رو شروع کردی جدول فاکتور و اقلام کالا لاک میشه و تراکنش دومی تا اتمام تراکنش اول به تعویق می افته و هیچ مشکلی هم در همزمانی رخ نمیده .
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.