PDA

View Full Version : جلوگیری از درج داده تکراری در پروسیجر و نمایش پیغام مناسب !



ghasem110deh
جمعه 27 شهریور 1394, 09:06 صبح
سلام به همه
توی پروسیجر درج از Not Exists استفاده کردم واسه جلوگیری از داده تکراری تو چند فیلد که نباید مقدار تکراری بگیرن !
مشکلی هم نداره (مقدار تکراری درج نمیشه)
اما مشکل نمایش پیغام مناسب به کاربره که متوجه بشه کدوم فیلد رو تکراری داده :


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

و توی برنامه هم از این استفاده کردم :


catch(SqlException e)
{
MessageBox.Show(e.ToString());
foreach (var error in e.Errors)
{
var exception = error as SqlError;
if(exception != null)
MessageBox.Show(string.Format("Number: {0} Message: {1}", exception.Number, exception.Message));
}
}


اگه هیچ کدوم از فیلدها تکراری نباشه درج انجام میشه ، منتها اگه یکی شون یا همشون تکراری باشه فقط خطای اول "Name is Exists" رو برمیگردونه !
چه کنم که بشه پیغام درست به کاربر داد که کدوم فیلد رو تکراری داده !؟

ممنون :)

ghasem110deh
شنبه 28 شهریور 1394, 17:28 عصر
دوستان ...
کسی علت مشکل رو نمیدونه ؟!
.
.
.
روش مهم نیست ، میخوام تو یک کوئری چند تا فیلد که نباید مقدار تکراری بگیرن رو با توجه فیلد مربوطه ، خطای مناسب رو به کاربر نشون بدم

SabaSabouhi
شنبه 28 شهریور 1394, 19:40 عصر
دوستان ...
کسی علت مشکل رو نمیدونه ؟!
.
روش مهم نیست ، میخوام تو یک کوئری چند تا فیلد که نباید مقدار تکراری بگیرن رو با توجه فیلد مربوطه ، خطای مناسب رو به کاربر نشون بدم

سلام
دلیل رو تقریباً من می‌دونم. شما یک مقایسه انجام دادی و انتظار داری 3 تا نتیجه بگیری. این نمی‌شه.
برای این منظور باید 3 بار query بگیری و نتیجه رو بررسی کنی که کار صحیحی نیست.

بجای این کار از اندیس یکتا استفاده کن. برای کلیه‌ی ستون‌هایی که می‌خوای تو دیتابیس یکتا باشن اندیس یکتا بگذار.
بعد تو برنامه از try catch استفاده کن و در صورت بروز خطا مقدار ex.Message رو بررسی کن اگه پیام حاوی Violation of UNIQUE KEY بود
معلومه که یکی از شرایط یکتا بودن نقض شده، کلمه‌ی بعدی تو این پیام خطا نام اندیسی هست که خطا داشته مثلاً IX_MyTable_2 که اندیس
یکتای دوم هست و می‌تونی از این‌جا بفهمی که کدوم قسمت تکراری وارد شده.

صبا صبوحی

ghasem110deh
شنبه 28 شهریور 1394, 20:39 عصر
ممنون جناب صبوحی :)
----
از فیلد یونیک استفاده کردم منتها نتونستم تشخیص بدم که خطا مربوط به کدوم فیلد هست (یعنی کدوم فیلد مقدار تکراری گرفته که کاربر رو توجیه کنیم)

http://barnamenevis.org/showthread.php?507005-%D8%AC%D9%84%D9%88%DA%AF%DB%8C%D8%B1%DB%8C-%D8%A7%D8%B2-%D8%AB%D8%A8%D8%AA-%D8%AF%D8%A7%D8%AF%D9%87-%D8%AA%DA%A9%D8%B1%D8%A7%D8%B1%DB%8C-%D8%A8%D8%AF%D9%88%D9%86-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%D9%BE%D8%B1%D9%88%D8%B3%DB%8C%D8%AC%D8%B1

الان سه تا فیلد رو یونیک کردم (هر کدوم هم یه اسم دارن)

golbafan
شنبه 28 شهریور 1394, 21:31 عصر
ممنون جناب صبوحی :)
----
از فیلد یونیک استفاده کردم منتها نتونستم تشخیص بدم که خطا مربوط به کدوم فیلد هست (یعنی کدوم فیلد مقدار تکراری گرفته که کاربر رو توجیه کنیم)

http://barnamenevis.org/showthread.php?507005-%D8%AC%D9%84%D9%88%DA%AF%DB%8C%D8%B1%DB%8C-%D8%A7%D8%B2-%D8%AB%D8%A8%D8%AA-%D8%AF%D8%A7%D8%AF%D9%87-%D8%AA%DA%A9%D8%B1%D8%A7%D8%B1%DB%8C-%D8%A8%D8%AF%D9%88%D9%86-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%D9%BE%D8%B1%D9%88%D8%B3%DB%8C%D8%AC%D8%B1

الان سه تا فیلد رو یونیک کردم (هر کدوم هم یه اسم دارن)


سلام
اگر سه تا فیلد رو یونیک کنید که معماری دیتابیس شما عوض میشه!!!

البته معمولا در این مواقع دیتابیس ها فقط به ذکر "ایندکس یونیک، تکرای است" اکتفا میکنن. حالا این ایندکس میتونه شامل یک یا چند فیلد بشه و نیازی هم به پروسیجر نیست. کافیه ارور ها رو هندل کنید

در مورد خطا هم آقای صبوحی درست میگن. چون از else استفاده شده پس فقط یک شرط رو دارید !!!

golbafan
شنبه 28 شهریور 1394, 21:38 عصر
در ضمن شما دارین از پروسیجری استفاده میکنین که سرعت دیتابیس رو خیلی میاره پایین. مشکلی نیست؟؟؟

SabaSabouhi
یک شنبه 29 شهریور 1394, 09:59 صبح
ممنون جناب صبوحی :)
----
از فیلد یونیک استفاده کردم منتها نتونستم تشخیص بدم که خطا مربوط به کدوم فیلد هست (یعنی کدوم فیلد مقدار تکراری گرفته که کاربر رو توجیه کنیم)

الان سه تا فیلد رو یونیک کردم (هر کدوم هم یه اسم دارن)

سلام
تصور کن این جدولت باشه:


CREATE TABLE MyTable (
Id INT IDENTITY ( 1, 1) NOT NULL,
Name NVARCHAR( 50) NOT NULL,
Number SMALLINT NOT NULL,

CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED ( Id ASC ),
CONSTRAINT [IX_MyTable] UNIQUE NONCLUSTERED ( Name ASC ),
CONSTRAINT [IX_MyTable_1] UNIQUE NONCLUSTERED ( Number ASC )
)

نام‌گذاری به شکلی هست که خود Management Studio انجام می‌ده، اما می‌تونی مثلاً بجای IX_MyTable از نام IX_MyTable_Name استفاده کنی.
باید توجه داشته باشی که نام اندیس باید در کل دیتابیس یگانه باشه، یعنی اگه از IX_Name استفاده کنی، تو جدول دیگه نمی‌تونی از این نام استفاده کنی.
حالا اگه تو این جدول نام تکراری وارد کنی تو متن خطایی که می‌گیری ( ex.Message ) کلمه‌ی IX_MyTable رو خواهی دید
و اگه شماره‌ی تکراری وارد کنی کلمه‌ی IX_MyTable_1 رو خواهی دید. و درست پس از عبارت Violation Of Unique Key.
پس می‌تونی به راحتی متوجه بشی که کدوم اندیس یکتا خطا رو تولید کرده.

صبا صبوحی

ghasem110deh
یک شنبه 29 شهریور 1394, 13:32 عصر
در ضمن شما دارین از پروسیجری استفاده میکنین که سرعت دیتابیس رو خیلی میاره پایین. مشکلی نیست؟؟؟
سرعتش خیلی پایین نبود که مشهود باشه (البته چون آزمایشی بود فقط یه جدول بود با 5 تا فیلد)
در هر صورت روش فیلد یونیک رو میرم جلو ، که دیگه نیازی به پروسیجر هم نباشه !؟

از هر دو بزرگوار ممنون :)

Seyyed_H_T
دوشنبه 30 شهریور 1394, 08:42 صبح
پیشنهاد می کنم (با در نظر گرفتن SRP یا SoC که اشاره می کنند به سپردن فقط یک مسئولیت به یک واحد عمل کننده) به جای لحاظ کردن هر دو عمل افزودن و بازگرداندن موارد تکراری را در یک Stored Procedure، برای هر مورد یک SP مجزا بنویسید که در این صورت در SP افزودن به پایگاه داده می توانید از همان دستور Not Exist یا حتی دستور MERGE استفاده کنید و در SP بعد با استفاده از دستور Exist موارد تکراری رو برگردونید.

golbafan
دوشنبه 30 شهریور 1394, 13:44 عصر
سرعتش خیلی پایین نبود که مشهود باشه (البته چون آزمایشی بود فقط یه جدول بود با 5 تا فیلد)
در هر صورت روش فیلد یونیک رو میرم جلو ، که دیگه نیازی به پروسیجر هم نباشه !؟

از هر دو بزرگوار ممنون :)

سلام
خواهش میکنم دوست عزیز...
منظورم تعداد رکوردهای زیاد هست :لبخندساده: