PDA

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



mr.sirwan
چهارشنبه 27 اسفند 1399, 13:24 عصر
سلام و درود دوستان
بنده توی برنامه م یه مشکلی دارم اینکه چند کاربر بصورت همزمان بخوان نامه جدیدی ثبت کنن، اندیکاتور این چند نامه تکراری ثبت میشه، در حالیکه همچین مساله ای خیلی حیاتیه و نباید دو نامه با اندیکاتور یکسان وجود داشته باشن.
درحال حاضر روال کاریم به این شکله که وقتی یه نامه ای ثبت میشه من اون اندیکاتوری که ثبت شده رو یه واحد بهش اضافه میکنم و به عنوان آخرین اندیکاتور توی جدولی به اسم IndicatorTable ذخیره میکنم، حالا هروقت پنجره ثبت نامه جدید باز شد میرم از این جدول رکورد مربوط به اندیکاتور نوع نامه رو میخونم و داخل فرم نمایشش میدم، جدول IndicatorTable به این شکله:
public class IndicatorTable
{
public IndicatorTable()
{
LastInterIndicator = 1;
LastImportIndicatior = 1;
LastExportIndicator = 1;
}

[Key, ForeignKey("WorkYear")]
public int Id { get; set; }

public int LastInterIndicator { get; set; }
public int LastImportIndicatior { get; set; }
public int LastExportIndicator { get; set; }

public virtual WorkYear WorkYear { get; set; }
}


خب همونطور که گفتم الان با مشکل ثبت تکراری اندیکاتور مواجه هستم در حالتی که همزمان چند کاربر نامه جدید ثبت کنن یعنی مشکل فقط در حالت همزمانی هستش وگرنه بصورت ترتیبی مشکلی پیش نمیاد و اندیکاتور ها بصورت مرتب افزایش پیدا میکنن

حالا برای رفع این مشکل من اومدم فک کردم که یه جدول جدید ایجاد کنم با عنوان InUseIndicator که هرموقع پنجره ثبت نامه جدید باز شد، اندیکاتور جدید توی این جدول ذخیره بشه تا زمانیکه نامه توسط کاربر ثبت نهایی میشه، موقعیکه شخص دیگه ای هم توی سیستم خودش پنجره ثبت نامه جدید رو باز کرد، نرم افزار بره داخل جدول اندیکاتورهای در حال استفاده (InUseIndicator) رو چک کنه و متناسب با اون یه اندیکاتور جدید تولید کنه
که خب این راه هم یه سری مشکل داره: وقتی دوتا کاربر بصورت همزمان بخوان نامه ثبت کنن بر فرض اندیکاتور 22 و 23 بهشون تعلق بگیره و داخل جدول InUseIndicator ذخیره بشن ممکنه کاربر اول که اندیکاتور 22 داره از ثبت نهایی کردن نامه انصراف بده ولی کاربر با اندیکاتور 23 نامه ش رو ثبت کنه، اون موقع اندیکاتور 22 جا میمونه و سری بعد که نامه جدیدی خواستن ثبت کنن، اندیکاتور از 24 شروع میشه
برای رفع این مشکل میشه از یه flag استفاده کرد ولی فک کنم دیگه زیادی پیچیده میشه

خواستم از دوستان و اساتید نظر بخوام که برای رفع این مشکل و قفل کردن اندیکاتور راه حل بهتری سراغ دارن؟

ronix3
چهارشنبه 27 اسفند 1399, 20:16 عصر
من خوب متوجه نشدم ولی چرا این اندیس موقع ذخیره محاسبه نمی شه؟
چرا وفتی هنوز کاربر کارش تموم نشده یه کد واسه نامه در نظر گرفته می شه؟

mr.sirwan
پنج شنبه 28 اسفند 1399, 11:33 صبح
ببینید منطق این کار به خاطر اینه که کاربر مجاز باشه و بتونه شماره اندیکاتور رو بصورت دلخواه تغییر بده، حالا این مورد شاید فقط توی یک درصد از حالات کاربرد داشته باشه و توی 99 درصد مواقع کاربر اصلا نیازی به تغییر اندیکاتور نداشته باشه ولی همچین قابلیتی باید داخل نرم افزار باشه که کاربر بتونه اندیکاتور رو تغییر بده، این صفحه ثبت یک نامه جدید داخل نرم افزارم هست


153158



**البته اگه راهی نبود انگار مجبور میشم همچین قابلیتی رو بردارم و صرفا بعد از ثبت نامه به کاربر اعلام کنم که اندیکاتور نامه جدیدت اینه و شماره نامه ت شده این

Mahmoud Zaad
پنج شنبه 28 اسفند 1399, 11:51 صبح
سلام
میشه در ابتدا یک شماره به کاربر نمایش بدید، در زمان ثبت نهایی در دیتابیس جستجو کنید اگر این شماره ثبت شده بود به کاربر پیغام بدید که شماره تکراریه، حالا اینجا هم دو تا راهکار هست یا اینکه خودش یک شماره جدید وارد کنه یا اینکه شما تابعی که برای این منظور دارید رو اجرا کنید و یک شماره جدید نمایش بدید و دوباره سند رو ذخیره کنه.
ضمنا نیازی به هیچ جدول دیگه ای نیست. در همون جدول اصلی می تونید آخرین اندیکاتور رو پیدا کنید.

mr.sirwan
پنج شنبه 28 اسفند 1399, 22:07 عصر
سلام
میشه در ابتدا یک شماره به کاربر نمایش بدید، در زمان ثبت نهایی در دیتابیس جستجو کنید اگر این شماره ثبت شده بود به کاربر پیغام بدید که شماره تکراریه، حالا اینجا هم دو تا راهکار هست یا اینکه خودش یک شماره جدید وارد کنه یا اینکه شما تابعی که برای این منظور دارید رو اجرا کنید و یک شماره جدید نمایش بدید و دوباره سند رو ذخیره کنه.
ضمنا نیازی به هیچ جدول دیگه ای نیست. در همون جدول اصلی می تونید آخرین اندیکاتور رو پیدا کنید.

ببینید من دقیقا در حال حاضر همین کار رو میکنم، یعنی یه بار موقعیکه فرم ثبت نامه جدید باز میشه، میرم آخرین اندیکاتور رو میخونم و داخل تکست باکسش قرار میدم، و یه بار هم دقیقا توی ایونت دکمه ثبت نامه وقتی که کاربر میخواد نامه رو ثبت نهایی بکنه این واکشی آخرین اندیکاتور رو دوباره انجام میدم صرفا به خاطر اینکه ممکنه چند کاربر بصورت همزمان فرم ثبت نامه رو باز کرده باشن و توی اون حالت برای اون چند کاربر یک اندیکاتور یکسان داخل تکست باکس ثبت شده باشه

این روش تا حدی جوابگو بوده ولی برای مواقعیکه کاربرا بصورت همزمان هرکدوم روی سیستم خودشون دکمه ثبت نامه رو بزنن بازم مشکل تکراری بودن اندیکاتور بوجود میاد، مواردی که پایین ذکر میکنم نتیجه مشاهدات بنده هستش برای چند کاربر که بصورت همزمان نامه ثبت کردن. اعدادی که در زیر میارم در قالب زمان هستش یعنی ساعت، دقیقه و ثانیه:

153160


برای مورد سوم جالب اینجاست که دوتا کاربر دقیقا در یک لحظه دکمه ثبت نامه رو زدن ولی با اینحال میبینیم که 4 ثانیه باهم اختلاف دارن، مسلما این اختلاف نباید از سمت برنامه بنده باشه و به یقین مربوط به تجیهزات شبکه اون سازمان میشه، اگه اشتباه میکنم لطفا بگین

خب حالا با این اوصاف پیشنهاد دوستان چیه؟ چه راهکاری رو پیش بگیرم؟

Mahmoud Zaad
پنج شنبه 28 اسفند 1399, 22:58 عصر
از تراکنش استفاده میکنید؟
برای روند کنترل تکراری نبودن و ثبت اطلاعات از چند کانکشن استفاده میکنید؟ یعنی با یک کانکشن تکراری بودن رو کنترل می کنید بعد کانکشن رو می بندید و مجددا برای ثبت یک کانکشن دیگه ایجاد میکنید؟

mr.sirwan
پنج شنبه 28 اسفند 1399, 23:11 عصر
از تراکنش استفاده میکنید؟
برای روند کنترل تکراری نبودن و ثبت اطلاعات از چند کانکشن استفاده میکنید؟ یعنی با یک کانکشن تکراری بودن رو کنترل می کنید بعد کانکشن رو می بندید و مجددا برای ثبت یک کانکشن دیگه ایجاد میکنید؟

خیر از تراکنش استفاده نمیکنم، توی ایونت کلیک دکمه ثبت نامه رو میفرمایید؟ بله اونجا با یه کانکشن، ابتدا اندیکاتور رو مجددا واکشی میکنم و بلافاصله اقدام به درج نامه در دیتابیس میکنم

Mahmoud Zaad
جمعه 29 اسفند 1399, 09:23 صبح
از تراکنش استفاده کنید. یک خاصیتی داره به اسم IsolationLevel که مشکل همزمانی رو رفع میکنه. توضیحات بیشتر (https://nikamooz.com/understanding-isolation-level-in-sql-server/)