PDA

View Full Version : مشکل در delete کردن یک ردیف خاص



mary3541
سه شنبه 29 اردیبهشت 1388, 09:51 صبح
میخوام وقتی یک ردیف خاص رو delet میکنم ابتدا از من بپرسه آیا مایل به حذف هستید؟ بعد با زدن دکمه yes اگر ID ردیف در جدول دیگری استفاده نشده بود ( در اصل به معنی اینکه این Id برای جدول دیگری کلید خارجی باشد و از آن در آن جدول استفاده شده باشد) حذف انجام شود و اگر استفاده شده باشد پیغام حذف انجام نشد را بدهد. کد زیر رو برای کلید حذف فرم Course جدول Course ، نوشتم ولی قسمت دوم کاری نمیکنه با اینکه Id این جدول در چند جدول به عنوان کلید خارجی هست


DialogResult dr = MessageBox.Show("آیا مایل به حذف اطلاعات هستید؟", "",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning,
MessageBoxDefaultButton.Button2);
if (dr == DialogResult.Yes)
{
try
{
int id = int.Parse(dgv.CurrentRow.Cells[0].Value.ToString());
cour.Delete(id);
refresh();
}
catch
{
MessageBox.Show("حذف انجام نشد");
}

به نظر شما باید چیکار کنم؟

seven7777777
سه شنبه 29 اردیبهشت 1388, 11:16 صبح
ییخشید کجای این کد چک کردید که کلید خارجی هست یا نه ؟؟؟

mary3541
سه شنبه 29 اردیبهشت 1388, 11:58 صبح
خب مشکل من همینه نمیدونم کجا و چجوری این کد رو وارد کنم؟

hsmfaridmehr
سه شنبه 29 اردیبهشت 1388, 12:50 عصر
این کدو من توی یکی از برنامه هام استفاده کردم

کد زیر مربوط به کلاس(جدول) مشتری که با کلاس(جدول) سرویس در ارتباط
که در یک تایع به اسم CheckRelation در صورت موجود بودن رابطه true و در غیر این صورت false برگردانده میشود



publicint DeleteData()
{
OleDbCommand command = newOleDbCommand();
try
{
connection.Open();
command.Connection = connection;
if (CheckRelation() && _allowDeleting)
{
command.CommandText = "DELETE * FROM Customer WHERE CustomerID =" +
_customerID;
command.ExecuteNonQuery();
return 2;
}
elseif (!CheckRelation())
{
command.CommandText = "DELETE * FROM Customer WHERE CustomerID =" +
_customerID;
command.ExecuteNonQuery();
return 2;
}
else
{
return 1;
}
}
catch
{
return 0;
}
finally
{
connection.Close();
command.Dispose();
}
}

privatebool CheckRelation()
{
Service service = newService();
service.CustomerID = _customerID;
if (service.GetData().Rows.Count > 0)
{
service = null;
returntrue;
}
service = null;
returnfalse;
}


و این هم کد مربوطه در فرمم هستش



privatevoid DeleteData()
{
if (dgvCustomer.Rows.Count > 0)
{
//Check if user really wants to delete the row
DialogResult dialogResult = PersianTools.PersianMessageBox.Show(" \"" +
dgvCustomer.CurrentRow.Cells[""].Value.ToString() +
" " + dgvCustomer.CurrentRow.Cells[" "].Value.ToString() +
"\" ", this.Text, PersianTools.PersianMessageBoxButtons.YesNo,
PersianTools.PersianMessageBoxIcon.Question, PersianTools.PersianMessageBoxDefaultButton.Button 1, 1, "");
if (dialogResult == DialogResult.Yes)
{
int checkRelation = 0;
customer = new TaxiCL.Customer();
customer.CustomerID = int.Parse(
dgvCustomer.CurrentRow.Cells[" "].Value.ToString());
checkRelation = customer.DeleteData();
if (checkRelation == 2)
{
SearchData();
}
elseif (checkRelation == 1)
{
//Check if user wants to delete all the relation in other tables
dialogResult = PersianTools.PersianMessageBox.Show(" .\n" +
" ." +
"\n ", this.Text, PersianTools.PersianMessageBoxButtons.YesNo,
PersianTools.PersianMessageBoxIcon.Information,
PersianTools.PersianMessageBoxDefaultButton.Button 1, 1, "");
if (dialogResult == DialogResult.Yes)
{
customer.AllowDeleting = true;
customer.DeleteData();
SearchData();
}
customer = null;
}
elseif (checkRelation == 0)
{
PersianTools.PersianMessageBox.Show(" .", this.Text,
PersianTools.PersianMessageBoxButtons.OK, PersianTools.PersianMessageBoxIcon.Error, PersianTools.PersianMessageBoxDefaultButton.Button 1, 1, "");
}
}
}

h.jaza
سه شنبه 29 اردیبهشت 1388, 18:20 عصر
نیازی به چک این کار نیست، اگر رکوردی که می خواین حذف کنین، رابطه ای خارجی با جداول دیگه داشته باشه، خود SQL Server اجازه ی حذفش رو نمیده...

و اگر نه، می خواین هر جوری که شده، حذف کنه، اونوقت باید کلید های خارجی رو بگیرن و برین از اون جداول، رکوردهای مرتبط رو حذف کنین و در نهایت برگردین و رکورد جاری رو هم حذف کنین...

hsmfaridmehr
سه شنبه 29 اردیبهشت 1388, 22:37 عصر
نیازی به چک این کار نیست، اگر رکوردی که می خواین حذف کنین، رابطه ای خارجی با جداول دیگه داشته باشه، خود SQL Server اجازه ی حذفش رو نمیده...

و اگر نه، می خواین هر جوری که شده، حذف کنه، اونوقت باید کلید های خارجی رو بگیرن و برین از اون جداول، رکوردهای مرتبط رو حذف کنین و در نهایت برگردین و رکورد جاری رو هم حذف کنین...


درست میگید ولی دوستمون می خواستن در صورت وجود پیغام داده بشه ولی در روش شما
اگر Exception دیگه ای هم رخ بده پیغام نشون داده میشه

h.jaza
سه شنبه 29 اردیبهشت 1388, 22:54 عصر
درسته در حالتیکه بخوایم ایرور ها رو به صورت جزئی نشون بدیم.

ولی اگر بخوایم با یه پیغام کلی نشون بدیم ...

mary3541
سه شنبه 29 اردیبهشت 1388, 23:40 عصر
باید حتما یه پیغام نشون بده.
شرمنده راه حلتون رو نفهمیدم میشه در موردش یکم توضیح بدید؟

hsmfaridmehr
چهارشنبه 30 اردیبهشت 1388, 00:08 صبح
خوب در اینجا من اول یک تابع واسه چک کردن این موضوع که رابطه ای با جداول دیگر وجود
دارد یا نه نوشتم(CheckRelation) که در این کد جدول مشتری با جدول سرویس در ارتباطه.

خوب هر وقت که کاربر قصد حذف رکورد را داشته باشه اول از موجود بودن رابطه اطمینان پیدا
میکنیم که اگر رابطه وجود داشته باشد و متغییر allowDeleting که از نوع بولین false باشه مقدار 1 به تابع DeleteData موجود در فرم مشتری برگردانده میشه و در فرم مشتری مقدار
بازگشتی چک میشه و در صورت 1 بودن پیغام "این رکورد با جداول دیگر در ارتباط........" نشان
داده میشود و در صورت تایید کاربر خصوصیت AllowDeleting موجود در کلاس مشتری برابر
true شده و دوباره تابع DeleteData کلاس مشتری صدا زده میشه و رکورد و تمام رابطه ها
حذف می شوند

در غیر این صورت اگر رابطه وجود نداشته باشد(CheckRelation مقدار false برگرداند) رکورد
حذف میشود

البته باید بگم که



service.GetData()


یک تابع در کلاس سرویس هستش که نسبت به داده ها در جدول جستوجو می کند
و یک DataTable بر می گرداند که در این جا ما CustomerID کلاس سرویس رو برابر با ID مشتری که باید حذف شود قرار دادیم و در صورت وجود رابطه تعداد سطرهای DataTable
بازگشتی باید از صفر بیشتر باشد

h.jaza
چهارشنبه 30 اردیبهشت 1388, 11:06 صبح
... در اینجا ...
بیشتر کجا، من لینکی نمی بینم...

بعدشم اصلا نیازی به انجام این تیپ کارا نیست، خود SQL زمانی که شما بخوای یه Refrence Record رو پاک کنی، بهت پیغام میده و در نهایت هم عملیات حذف رو انجام نمیده:



The DELETE statement conflicted with the REFERENCE constraint \"ForignKeyName"\


با استفاده از این امکان، خیلی ساده میشه با تطبیق ارور، پیغام مناسب رو به کاربر نشون داد...

hsmfaridmehr
چهارشنبه 30 اردیبهشت 1388, 11:26 صبح
بیشتر کجا، من لینکی نمی بینم...


کد بالا رو منظورم بود

این کد در صورتی که "Enforce Relational Integrity" رو فعال کرده باشید در صورت
وجود رابطه با جدولی دیگر پیغام میده که این رکورد با جدولی دیگر رابطه داره و از کاربر می پرسه
که آیا مایل به حذف رکورد و دیگر رابطه ها هست یا نه که در صورت تایید کاربر هم رکورد و هم
دیگر رکورد های مربوط به این رکورد در جدول های دیگر حذف می شود.

البته حرف شما هم کاملا درسته ولی واسه ی تفکیک Message ها من این کار رو انجام دادم

mary3541
چهارشنبه 30 اردیبهشت 1388, 13:10 عصر
بیشتر کجا، من لینکی نمی بینم...

بعدشم اصلا نیازی به انجام این تیپ کارا نیست، خود SQL زمانی که شما بخوای یه Refrence Record رو پاک کنی، بهت پیغام میده و در نهایت هم عملیات حذف رو انجام نمیده:



The DELETE statement conflicted with the REFERENCE constraint \"ForignKeyName"\



با استفاده از این امکان، خیلی ساده میشه با تطبیق ارور، پیغام مناسب رو به کاربر نشون داد...




منظورتون اینه که نیازی نیست تو کدم تغییری ایجاد کنم؟

The DELETE statement conflicted with the REFERENCE constraint \"ForignKeyName"\
این قسمتو باید جایی وارد کنم؟اگه جواب مثبته کجا؟

NewFoxStudent
چهارشنبه 30 اردیبهشت 1388, 15:06 عصر
منظورتون اینه که نیازی نیست تو کدم تغییری ایجاد کنم؟


نیاز به یک تغییر کوچک در کد هست و اون هم استفاده از یک Try Catch هست
با استفاده از Try Catch شما موقع حذف رکورد اگر خطایی رخ بده با کنترل پیغام یا کد خطا متوجه میشید که آیا خطا به خاطر ارتباط کلید خارجی با یک جدول دیگه هست یا نه و اگه اینطور بود پیغام مناسب رو به کار بر میدید


کد:
The DELETE statement conflicted with the REFERENCE constraint \"ForignKeyName"\
این قسمتو باید جایی وارد کنم؟اگه جواب مثبته کجا؟

نیازی به اضافه کردن این قسمت نیست
این پیغام خطایی که Sql موقع حذف یک رکورد که کلید خارجیه اون جای دیگه استفاده شده برمیگردونه

mary3541
چهارشنبه 06 خرداد 1388, 14:15 عصر
نیاز به یک تغییر کوچک در کد هست و اون هم استفاده از یک Try Catch هست
با استفاده از Try Catch شما موقع حذف رکورد اگر خطایی رخ بده با کنترل پیغام یا کد خطا متوجه میشید که آیا خطا به خاطر ارتباط کلید خارجی با یک جدول دیگه هست یا نه و اگه اینطور بود پیغام مناسب رو به کار بر میدید



نیازی به اضافه کردن این قسمت نیست
این پیغام خطایی که Sql موقع حذف یک رکورد که کلید خارجیه اون جای دیگه استفاده شده برمیگردونه
من از Try Catch استفاده کردم به صورت زیر اما هنگام اجرا وقتی حذف ردیفی که IDیی که به عنوان کلید خارجی برای جدول دیگس رو میخوام انجام بدم حذف انجام نمیشه ولی هیچ پیغامی نشان نمیدهد
باید چه تغییری بدم؟


privatevoid btnDelete_Click(object sender, EventArgs e)
{
DialogResult dr = MessageBox.Show("آیا حذف انجام شود؟", "",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning,
MessageBoxDefaultButton.Button2);
if (dr == DialogResult.Yes)
{
try
{
int id = int.Parse(dgv.CurrentRow.Cells[0].Value.ToString());
cour.Delete(id);
refresh();
}
catch
{
MessageBox.Show("حذف انجام نشد");
}
}
}

NewFoxStudent
چهارشنبه 06 خرداد 1388, 14:33 عصر
ممکنه کد مربوط به تابع delete رو هم اینجا بزارید

mary3541
چهارشنبه 06 خرداد 1388, 15:09 عصر
ممکنه کد مربوط به تابع delete رو هم اینجا بزارید





public void Delete(int Course_ID)
{
string str = "delete from [Course] where [Course_ID] = " + Course_ID;
db.DoCommand(str);
}

NewFoxStudent
چهارشنبه 06 خرداد 1388, 17:32 عصر
لطف کنید و کد تابع DOCommand رو هم بزارید و اگه داخل اون تابع دیگه ای رو فراخوانی کردید کد اون رو هم بزارید
من با Try تست کردم و جواب هم داد منتها تمام عملیات حذف رو داخل همون try انجام دادم و از تابع استفاده نکردم

mary3541
چهارشنبه 06 خرداد 1388, 18:22 عصر
لطف کنید و کد تابع DOCommand رو هم بزارید و اگه داخل اون تابع دیگه ای رو فراخوانی کردید کد اون رو هم بزارید
من با Try تست کردم و جواب هم داد منتها تمام عملیات حذف رو داخل همون try انجام دادم و از تابع استفاده نکردم


چون برنامم سه لایه هست.Docommand رو توی کلاس Dal نوشتم


public void DoCommand(string sql)
{
try
{
connect();
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
catch
{ }
finally
{
con.Close();
}
}

mary3541
چهارشنبه 06 خرداد 1388, 18:46 عصر
لطف کنید و کد تابع DOCommand رو هم بزارید و اگه داخل اون تابع دیگه ای رو فراخوانی کردید کد اون رو هم بزارید
من با Try تست کردم و جواب هم داد منتها تمام عملیات حذف رو داخل همون try انجام دادم و از تابع استفاده نکردم


تابع delete به درستی انجام میشه فقط برای ردیفهایی که ID آنها به عنوان کلید خارجی هست delete انجام نمیشه تا اینجا که درسته فقط باید پیغام اینکه این کلید خارجی است و در جایی دیگه از آن استفاده شده رو نمیدهد

NewFoxStudent
چهارشنبه 06 خرداد 1388, 19:08 عصر
خوب حالا شد
شما چند راه دارید
یکی اینکه توی تابع DoCommand توی قسمت catch خطایی رو که اتفاق میفته کنترل کنید و پیغام مناسب بدید
که البته با توجه به لایه ای بودن برنامه شما راه درستی نیست
یکی اینکه یه کلاس فرضا با نام ErrorHandling درست کنید و توی قسمت catch تابع DoCammand یه نمونه ازش بسازید و خطا هاتون رو هندل کنید
راه دیگه اینه که نوع بازگشتی تابع DoCommand رو تغییر بدید مثلا به int و توی قسمت catch اگه خطای مورد نظرتون اتفاق افتاد یه مقدار از پیش تعیین شده به تابع Delete برگردونید و اونجا این پیغام رو بدید
ولی برای امتحان همین الان میتونید توی قسمت catch تابع DoCommand یه MessageBox بزارید و ببینید که کار میکنه

mary3541
چهارشنبه 06 خرداد 1388, 20:09 عصر
ممنون درست شد
حالا اگه بخوام تو ویرایش هم به همین صورت بشه باید همین مراحل رو طی کنم؟

NewFoxStudent
پنج شنبه 07 خرداد 1388, 12:46 عصر
این روش یکی از راه هایی هست که میتونید استفاده کنید

mahangroup
پنج شنبه 30 شهریور 1391, 21:19 عصر
با سلام
من یک روش خیلی راحت برای حذف یک ردیف دارم
کافی کد زیر رو در button که می خواهد با زدن ان ردیف حذف گردد قرار دهید.

if (dataGridView1.CurrentCell.ColumnIndex != 0)
{
MessageBox.Show("لطفا ستون شماره را برای حذف انتخاب نمایید ", "اخطار");
return;
}
else
{
int ID = Convert.ToInt32(dataGridView1.CurrentCell.Value.To String());
SaveData DeleteData = new SaveData();
DeleteData.CommandExec("delete from Driver where ID=" +ID + "");
dataload();

}

ورود به سایت شرکت اینجانب (http://www.mahngroup.ir)

mahangroup
پنج شنبه 30 شهریور 1391, 21:22 عصر
با سلام
این یک روش خیلی راحت برای حذف یک ردیف در dataGridView است

if (dataGridView1.CurrentCell.ColumnIndex != 0)
{
MessageBox.Show("لطفا ستون شماره را برای حذف انتخاب نمایید ", "اخطار");
return;
}
else
{
int ID = Convert.ToInt32(dataGridView1.CurrentCell.Value.To String());
SaveData DeleteData = new SaveData();
DeleteData.CommandExec("delete from Driver where ID=" +ID + "");
dataload();

}


ورود به سایت شرکت اینجانب (http://www.mahangroup.ir)

tooraj_azizi_1035
جمعه 31 شهریور 1391, 09:55 صبح
با فرض اینکه Order و OrderDetails داریم:


var result = from o in Orders.AsEnumerable()
join od in OrderDetails.AsEnumerable() on o.OrderID equals od.OrderID
select o;

if(o.Count()==0)
//Now you can delete.
else
//You can not!

omidamiry
جمعه 31 شهریور 1391, 16:49 عصر
چرا سختش میکنید؟
مگه sql چکار انجام میده
میاد چک میکنه اگه کلید خارجیه کجاها استفاده شده (بانک های مرتبط) اگه مقدار جستجو true بود پیغام میده و نمیذاره در غیر اینصورت حذف میکنه


حالا شماهم همینکارو بکنید مگه نخایتا چندتا جدوله 10 تا بیشتره ؟

واسه id ده تا select بنویسید اگه result در هر مرحله true شد پیغام میدید که این id استفاده شده و امکان حذف نیست بعدشم خود کاربر می دونه که هر قسمت از برنامش با کدوم
قسمت برنامش در رابطه است چون شما این مطلبو در راهنمای نرم افزار ذکر میکنید

خلاص

اگر سوالی داشتید لطفا آدرس تاپیکو پیام خصوصی کنید