PDA

View Full Version : جلوگیری از انتقال زیر مجموعه به مجموعه



shahab_ksh
چهارشنبه 22 فروردین 1386, 14:58 عصر
جدول زیر رو در نظر بگیرید

name | id | ref_id |


computer | 1 | root |
economic | 2 | root |
asp.net | 3 | 1 |
vb.net | 4 | 1 |
ado.net | 5 | 1 |
ajax.net | 6 | 3 |


فیلد name فرض کنید نام کتابها می باشد
فیلد id کلید منحصر به فرد هر سطر می باشد
فیلد ref_id نگه دارنده این هست که عضو کدام مجموعه هست


برای مثال در مورد "computer" مقدار root نشاندهنده این هست که ریشه است


در مورد asp.net مقدار فیلد ref_id که 1 است نشاندهنده این است که زیر مجموعه computer است


computer > asp.net > ajax.net
computer > vb.net
computer > ado.net
< economic


خوب حالا میخام یه امکان انتقال رو هم به این برنامه بدم برای مثال بتونه ajax.net رو به ado.net انتقال بده
مشکلی برای ساخت این برنامه نیست
تنها مشکل اینه که نباید مجموعه های ماقبل به مجموعه های ما بعد انتقال پیدا کنه برای مثال
نباید computer یا vb.net به ajax.net انتقال پیدا کنه


با توجه به این مشکل چطور این رو تست کنم که یک انتقال باید انجام بشه یا نشه

babi_wd
چهارشنبه 22 فروردین 1386, 15:42 عصر
خیلی سخته نیم ساعته همین جا موندم دارم روش فکر میکنم
باید وقت بدی تا اساتید هم نظری بدن

Alireza_Salehi
چهارشنبه 22 فروردین 1386, 16:54 عصر
یه سوالی که وجود داره اینه که این ساختار سطوحش محدوده یا نامحدود؟
اگر محدود باشه خیلی راحت تره.
فکر نمیکنم راه اتوماتیکی برای این کار موجود باشه ، میتونی یک Query بنویسی که مشخص کنه مقدار مورد نظر در چه سطحی قرار داره و اگر مقداری که قراره منتقل بشه سطحش کمتره این کارو انجام نده!

در پایگاه داده رابطه ای پیاده سازی چنین ساختارهایی که حالت بازگشتی دارند یه کم کار میبره از XML استفاده کنید خیلی راحت تره، ساختار سلسله مراتبی داره.

babi_wd
چهارشنبه 22 فروردین 1386, 17:24 عصر
خوب
این راه حل نیست یه پیشنهاده
میتونی دو تا فیلد دیگه به نامهای IsChild و HaveChild به ساختارت اضافه کنی که True با False باشن
نسبت به جایگاه هر کدام از زیر مجموعه ها مقدار اونا فرق میکنه
مثل


Comouter>Asp.net>Ajax.net
Computer>Ado.net

برای این مجموعه:
خاصیت IsChild برای Computer مقدار False داره که نشون دهنده Root و خاصیت HaveChild مقدار True داره که نشون میده زیر مجموعه داره
برای Asp.net هر دو خاصیت True می باشد
برای Ajax.net فقط خاصیت IsChild ،True می باشد

برای مجموعه دوم :
خاصیت IsChild برای Computer مقدار False داره که نشون دهنده Root و خاصیت HaveChild مقدار True داره که نشون میده زیر مجموعه داره
برای Ado.net فقط خاصیت IsChild،True می باشد

با این توضیحات شما فقط مجوز جابجا کردن زیر مجموعه هایی رو دارین که خاصیت IsChild آنها True و HaveChild آنها False باشد

shahab_ksh
چهارشنبه 22 فروردین 1386, 21:01 عصر
تعداد شاخه ها و زیر شاخه ها نامحدوده

خیلی راحت بگم شبیه دایرکتوری موجود در هارده برای مثال

میشه راحت دایرکتوری program files رو cut به دایرکتوری widnows انتقال داد
اما نمیشه دایرکتوری windows رو cut به دایرکتوری system32 انتقال داد

البته اینجا دایرکتوری که الگوی من دایرکتوری نیست بلکه یه بانک اطلاعاتی که شاخه و شاخه شده

حالا من میخام کاری کنم که تشخیص بدم ایا مثلا میشه asp.net رو به ajax انتقال داد یا نه
که نباید بشه

اما مثلا بشه asp.net رو به economic انتقال کرد
؟؟؟؟
از babi و دیگر دوستان هم ممنون که رو این موضوع فکر میکنن

ghabil
چهارشنبه 22 فروردین 1386, 23:44 عصر
خیلی هم سخت نیست باید ریکرسیو بنویسیش قبلا تابع ریکرسیو حرکت روی درخت رو با دلفی اینجا نوشتم (http://www.barnamenevis.org/forum/showthread.php?t=48360)یک نگاهی بهش بکن پیاده سازی کاری که میخوای بکنی دقیقا بهمین روش و بصورت ریکرسیو باید انجام بشه.
کد رو ببین اگر دقت کنی خیلی شبیه کار تو هست ، اگر نتونستی راه بندازیش بگو با هم اینجا یک کاریش میکنیم.

صابر
چهارشنبه 22 فروردین 1386, 23:45 عصر
با یک تابع بازگشتی به راحتی مشکلتون حل میشه.
باید به صورت بازگشتی بررسی کنید که id آیتمی رو که میخواین انتقال بدین، توی ref_id جایی که میخواد بره وجود داره یا نه. (شرط پایان بازگشتی هم ref_id==root یا ref_id==id باشه)
اگه تابع بازگشتی بهref_id==root رسید مشکلی برای انتقال نیست. اما اگه قبل از اون به ref_id==id رسید انتقال غیر ممکنه.

مثلاً Ajax.Net قراره زیرشاخه computer بشه.
چون 6 با ref_id شاخه computer مساوی نیست و ref_id شاخه computer برابر با root هست مشکلی نیست.

یه مثال دیگه:
computer قراره زیرشاخه Ajax.Net بشه.
تابع بازگشتی میبینه که id شاخه computer مساوی با id شاخه Ajax.Net نیست و ref_id هنوز root نیست. یک مرحله دیگه میره (این بار با id شاخه ASP.Net که توی مرحله قبل به دست اومد) میبینه که ref_id شاخه ASP.Net با ref_id شاخه computer یکیه و اجازه move نمیده.

صابر
چهارشنبه 22 فروردین 1386, 23:47 عصر
ببخشید من پست آقای ghabil رو ندیده بودم (البته طبیعیه، چون 1 دقیقه اختلاف وجود داره!!)

babi_wd
پنج شنبه 23 فروردین 1386, 01:49 صبح
پس پیشنهاد من عملی نیست
اما پیمایش بازگشتی اونم تو دیتا بیس عاقلانه هست؟

صابر
پنج شنبه 23 فروردین 1386, 11:28 صبح
توی دیتابیس این کارها انجام نمیشه.
وقتی که لیست شاخه ها رو کاربر میبینه، یعنی یک بار request داده شده و اطلاعات گرفته شدن.
حالا روی این اطلاعات (مثلاً توی Data Table) این کارها انجام میشه.
استفاده از راه حل بازگشتی زمانی هزینه داره که احتمال پر شدن حافظه زیاد باشه.
مگه این شاخه ها حد اکثر چند level دارن؟ بیش از صد level؟ ندارن!

MM_Mofidi
شنبه 25 فروردین 1386, 13:29 عصر
اگر مشکلی در عضو شدن مثلا economic در ajax.net نباشه( یعنی فقط هر عضویت در شاخه خودش بررسی بشه)کار راحته.
راه حل: شما یک مسیر از فرزند نهایی تا پدر اصلی(root) تشکیل دهید سپس مقایسه کنید که آیا عضو جدید در مسیر هست یا نه ؟

shahab_ksh
شنبه 25 فروردین 1386, 15:10 عصر
ممنون از همه دوستان راستش شاید باورتون نشه الگورتمم از روز اول ایراد نداشت
من تمام این کارها رو باید در استوری پروسجر انجام میدادم که یه قسمت من همچین مقایسه ای انجام دادم



While (@str='root'
begin
end


که این کد از ریشه مشکل داره و فقط اعداد رو مقایسه میکنه نه مثلا این کد بالا رو که رشته هست

هیچ اروری هم از من نگرفت و من چند روزی فقط روی الگوریتم کار کردم تا اینکه هیج جا ندیدم

از حقله while برای رشته استفاده کنن
کل استوری پروسجر رو میزارم اینجا دوستان اگه خواستن استفاده کنن

الگوریتم هم اینه و سادست : مثلا اگه قراره

computer > asp.net > ajax.net
computer > vb.net
computer > ado.net
< economic


رو داشته باشیم فرض کنید asp.net رو قراره در ajax.net انتقال پیدا کنه کافی از ajax.net تا جایی که ریشه هست پیش بریم اگه اگه در مسیر بازگست به asp.net برخورد کردیم پس انتقال انجام نشه


البته تو اون مثالی که من از اول زدم کلید ها رو id , ref_id در نظر گرفتم که هر دو نوع عددی بودن در مثال اصلی خودم از guid استفاده کردم



ALTER PROCEDURE dbo.MenuMove
/*
(
@parameter1 int = 5,
@parameter2 datatype OUTPUT
)
*/
(
@par_id int,
@par_ref Nvarchar (MAX),
@par_stat Nvarchar (MAX),
@par_out nvarchar (MAX) output
)
AS
/* SET NOCOUNT ON */
Declare @str_first Nvarchar (MAX)
Select @str_first=(Select fld_ref From tbl_menu Where @par_id=fld_id)

/* در حال انتقال MIN یا MAX تعیین */
Declare @str_maxmin int
If @par_stat='Max'
Begin
Select @str_maxmin=(Select Max (fld_rank) From tbl_menu Where fld_ref=@par_ref)
Select @str_maxmin=@str_maxmin+1
End
If @par_stat='Min'
Begin
Select @str_maxmin=(Select Min (fld_rank) From tbl_menu Where fld_ref=@par_ref)
Select @str_maxmin=@str_maxmin-1
End

If (Select Count(*) From tbl_menu Where fld_ref=@par_ref) = 0
Begin
Select @str_maxmin = 0
End


/* تعیین آپدیت */
Declare @str_last Nvarchar (MAX)
Select @str_last=@par_ref

If (@str_last=@str_first)
/* اگر به مسیر فعلی انتقال پیدا کرد */
Begin
Declare @str_noon Nvarchar (MAX)
End
Else
/* اگر به مسیری غیر از مسیر فعلی انتقال پیدا کرد */
Begin
If (@str_last='root')
/* بود root اگر مسیر نمهایی */
Begin
Update tbl_menu Set fld_ref=@par_ref,fld_rank=@str_maxmin Where @par_id=fld_id
End
Else
/* نبود root اگر مسیر نمهایی */
Begin

Declare @str_true Nvarchar (MAX)
Declare @str_var int
Declare @str_var_guid Nvarchar (MAX)

Select @str_var=(Select fld_id From tbl_menu Where @par_ref=fld_guid) /* مسیر نمهایی */
Select @str_var_guid=@par_ref




WHILE NOT EXISTS (Select fld_ref From tbl_menu Where @str_var_guid='root')
Begin

Select @str_var=(Select fld_id From tbl_menu Where fld_guid=@str_var_guid)
Select @str_var_guid=(Select fld_ref From tbl_menu Where fld_guid=@str_var_guid)

If (@str_var=@par_id)
Begin
Select @str_true='false'
Break
End

End

If (@str_true='false')
Begin
Select @par_out='no-move'
End
Else
Begin
Update tbl_menu Set fld_ref=@par_ref,fld_rank=@str_maxmin Where @par_id=fld_id
End




End
End

RETURN



یه سری کارهای اضافه تر هم انجام میده که میتونید خودتون متوجه بشید
فقط بگم که

@par_id به عنوان آیدی فرض کنید منویی که میخاد انتقال داده بشه هستش
@par_ref مسیری که به اونجا منتقل میشه و البتهاز نوع guid هستش
par_out هم نتیجه کار آیا انتقال انجام بشه یا نه