PDA

View Full Version : سوال: جلوگیری از ثبت داده تکراری بدون استفاده از پروسیجر



ghasem110deh
شنبه 14 شهریور 1394, 00:02 صبح
سلام به همه ...
------------------
از این کدهای زیر واسه جلوگیری از ثبت داده تکراری تو جدول استفاده کردم ...
این لایه دیتااکسس :


public int Get_Name(string Name)
{
object R_Value = ExecuteScaler(System.Data.CommandType.Text, "SELECT * FROM Tbl_User Where Name = @u", new SqlParameter[]
{
new SqlParameter("@u", Name)
});
if (R_Value != null)
return Convert.ToInt32(R_Value);
else
return 0;
}


این لایه بیزنس :


RGF_DAL.User_Dal users = new RGF_DAL.User_Dal();
int R_Value = 0;
if (users.Get_Name(Name) != 0)
{
R_Value = 1; // نام قبلا ثبت شده است
}
if (R_Value == 0 && users.Get_User_Name(User_Name) != 0)
{
R_Value = 1; // نام کاربری قبلا ثبت شده است
}
if (R_Value == 0)
{
users.Add_User(Name, User_Name, User_Pass, Security_Question, Answer);
}
return R_Value;


اینم پشت فرم :


int R_Value = User_Bll.AddNewUser(Txt_Name.Text, Txt_Username.Text, Txt_UserPass.Text, comboBox1.Text, Txt_Question.Text);
switch (R_Value)
{
case 1:
MessageBox.Show("نام تکراری است");
break;
case 2:
MessageBox.Show("نام کاربری تکراری است");
break;
case 0:
MessageBox.Show("کاربر با موفقیت ثبت شد");
break;
}


ولی کلا همه چیو تکراری میدونه (حتی تکست باکس خالی رو )
مشکل از کجاست ؟

Mahmoud.Afrad
شنبه 14 شهریور 1394, 01:35 صبح
ستونهایی که داده غیرتکراری میپذیرند رو میتونید unique کنید. در اینصورت نیاز به چک کردن قبل از درج اطلاعات نیست و با تکراری بودن داده، یک استثناء پرتاب میشه که از روی شماره خطا میتونید به کاربر هشدار لازم رو بدید.
http://www.w3schools.com/sql/sql_unique.asp
http://stackoverflow.com/questions/24740376/best-way-to-catch-sql-unique-constraint-violations-in-c-sharp-during-inserts?answertab=active#tab-top (http://www.w3schools.com/sql/sql_unique.asp)

pbm_soy
شنبه 14 شهریور 1394, 01:51 صبح
مندکد شما را بطور دقیق مطالعه نکردم ولی ظاهر مشکلی ندارد!
معمولا برای برطرف کردن چنین خطاهایی تنها راه شما trace , debug کردن است! و مرحله به مرحله مقادیر متغیرها ومقادیر برگشتی توابعدرا بررسی کنید اینکار را نیز از سطوح بالا شروع کنید یعنی اول وارد لایه های پایین نشوید همون توابع و متغیرها را در سطح فرم بررسی کنید و ببینید کدامیک مقدار درستی به شما نمیدهد تا دفعه بعد که trace میکنید وارد آن تابع شوید و آنرا خط به خط اجرادکنید و بررسی کنید
شاید ایراد از لایه بالا باشد وشاید از لایه وسط و یا پایینی باشد
در ضمن فقط مقادیر خروجی را بررسی نکنید شاید ازذمقادیر ارسالی شما بداخل لایه ها هم باشد
مورد دیگر فقط به این سه تابع محدود نشوید شاید در لایه مورد نظر متغییری دارید ویا تابعی دارید و یا حتی سازنده ای دارید که بصورت مستقیم ویا غیر مستقیم بروی مقادیر ورودی یا خروجی تاثیر بگذارند

pbm_soy
شنبه 14 شهریور 1394, 01:53 صبح
میتوانید بجای عملیات trace در هر مرحله مقادیر دلخواه را نمایش دهید
حالا بروی فرم و یا بصورت messagebox ویا بصورت لاگ نمایش دهید

ghasem110deh
شنبه 14 شهریور 1394, 12:47 عصر
سلام و ممنون از هر دو عزیز
------------------------------
کد خودم رو نتونستم درست کنم ، روشی که آقا محمود گفتن رو رفتم ... کار میکنه
فقط یه مشکل که هست اگه داده تکراری نباشه آیدی ها به ترتیب اضافه میشه ، ولی اگه کاربر نام کاربری تکراری بده
ثبت (insert) انجام نمیشه ولی آیدی یکی اضافه میشه
و در صورت درج اطلاعات بعدی ترتیب آیدی ها میریزه به هم (فیلد آیدی identity هست)

pbm_soy
چهارشنبه 18 شهریور 1394, 02:15 صبح
اتفاقا روش اون دوستمون منطبق بر استانداردهای مفاهیم دیتابیس است البته خیلی از برنامه نویسها ایرادات کوچیکی به آن میگیرند نمونه اش همین ایراد شما !
ولی ایراد شما قابل چشم پوشی است اگر فیلد آی دی را برای تولید یک کلید اصلی منحصربفرد ایجاد کرده باشید ولی از این فیلد برای مشخص کردن شماره ردیف باشد قضیه فرق میکند

فیلدهای از نوع Identity شماره ردیف نیستند و هیچ ضمانتی در نپهداری صحیح ردیف ندارد ولی همیشه از کوچیک به بزرگ پیشرفت میکند (برعکسش نیز قابل تنظیم است) ولی اگر رکوردی حذف شود این شماره از بالا به پایین اصلاح نمیشوند شماره ای که حذف شده دیگه حذف شده!

ولی برویم سراغ کد خودتان در پست اول آیا کارهایی که من گفتم را انجام داده اید؟!
میتوانید کل پروژه و فایل دیتابیس را اینجا بذارید تا بررسی کنیم نیازی نیست کل پروژه باشد فقط همین یک فرم و دیتابیس و کلاسهای وابسطه به آن را بگذارید!

ghasem110deh
سه شنبه 24 شهریور 1394, 23:37 عصر
سلام
مجبور شدم از پروسیجر استفاده کنم باز :(
------
منتها یه مشکل که هست اینه که چطور تشخیص بدم کدوم وریبل مقدار تکراری داره که به کاربر پیغام بدم !؟

ghasem110deh
پنج شنبه 26 شهریور 1394, 13:33 عصر
سلام
من تو پروسیجر اینطور عمل کردم :


ELSE IF (@Name = @N)
RAISERROR('Name is Exists',16,1)
ELSE IF (@User_Name = @U)
RAISERROR('User_Name is Exists',18,1)
ELSE IF (@User_Pass = @UP)
RAISERROR('User_Pass is Exists',20,1) RETURN

که بتونم خطا رو بر حسب تکراری بودن یکی از سه متغیر ورودی برگردونم ،
حالا تو برنامه اینطور نوشتم : (اگه تکراری نبود ذخیره میشه)


catch (SqlException ex)
{
if (ex. ???)
{
MessageBox.Show("نام تکراری است");
}
else if (ex. ???)
{
MessageBox.Show("نام کاربری تکراری است");
}
else (ex. ???)
{
MessageBox.Show("کلمه عبور تکراری است");
}
}


حالا چطور میشه تشخیص داد کدوم خطا رخ داده ؟
مثلا اگه بلوک تری_کش رو بردارم و نام تکراری بدم خطای "Name is Exists" رو میده ...
اگه از ex.Number هم استفاده کنم چون کدهاش معلوم نیست درج نمیشه ولی خطایی که به کاربر بفهمونه کدوم مورد رو تکراری وارد کرده هم صادر نمیشه !

چه کنم ؟!؟