PDA

View Full Version : این برنامه مشکلش کجاست؟(autonumber)



asefy2008
جمعه 02 مرداد 1388, 10:58 صبح
سلام دوستان
برنامه ای که در ضمیمه موجود است با برداشتن این قطعه کد مشکلش حل میشه :



DataGridView[0,e.RowIndex].Value = e.RowIndex + 1;


حالا چی کار میشه کرد که این مشکل پیش نیاد؟(البته غیر از برداشتن اون قطعه کد)
اگر راه دیگه ای هم به نظرتون میرسه خوشحال میشم بدونم البته راه های زیادی هست ولی هیچ کدومشون این قدر خوب نبود(این کد تنها مشکلش همینه)
پیشا پیش از راهنمایی هاتون ممنوم

asefy2008
جمعه 02 مرداد 1388, 14:11 عصر
اینم یه تصویر از مشکل به وجود اومده در هنگام اجرا:

http://i39.tinypic.com/2yxjgci.jpg

SMRAH1
جمعه 02 مرداد 1388, 16:47 عصر
سلام

پیغام CellFormatting وقت ارسال میشه که برنامه مقداری رو برای یک سلول دریافت کرده و می خواهد نمایش دهد.حالا شما در این پیغام دوباره مقدار اون سلول رو تغییر دادی.چی میشه؟دوباره پیغام صدا زده می شه و ... این یعنی به وجود آوردن یک loop بدون پایان از فراخوان پیغام CellFormatting.برای همین برنامه به حالت تقریا قفل شده می ره.برای رفع این مشکل به جای بیغام CellFormatting ، پیغام RowsAdded رو بگیر و پردازش کن (با همون کد).

موفق باشی

asefy2008
جمعه 02 مرداد 1388, 17:26 عصر
ممنون دوست من می دونم تو loop می افته ولی نمی دونم تو چه رویدادی قرار بدم تا درست کار کنه رویدادی که شما فرمودین رو امتحان کردم ولی کار نکرد.

SMRAH1
جمعه 02 مرداد 1388, 17:30 عصر
سلام

کار می کنه!این هم تغییرات خودم در برنامه شما !

موفق باشی

asefy2008
جمعه 02 مرداد 1388, 17:43 عصر
بله درست می فرمایید کار می کنه ولی درست کار نمی کنه(شما چند سطر به اون اضافه کنید ببینید چی میشه.)

محمدامین شریفی
جمعه 02 مرداد 1388, 20:35 عصر
علی جان،لطفا cross topic (http://barnamenevis.org/forum/showthread.php?t=158397&page=2) نزن.
سلولی را که bind کردی،داری روش format می زاری.
یعنی یک بار format میشه و بار دیگه bind.نتیجه->refresh دیتا گرید ویو.
همانطور که گفته شد،CellFormatting تنها رویداد مناسب است.
فیلد nchar که در این برنامه بعنوان کلید اصلی استفاده شده است،اشتباه محض است.

پیروز باشید.

asefy2008
جمعه 02 مرداد 1388, 21:54 عصر
بله شما درست می فرمایید با این که دارم سعی می کنم اشتباه نکنم ولی مثل اینکه ترک عادت موجب مرض است. به خاطر این اشتباه از همه عذر می خواهم.
حالا چی کار میشه کرد ، بد جوری گیرم ، هر چی فکر می کنم راهی به ذهنم نمیرسه(اگر بخوام از این رویداد استفاده نکنم کلی خط به برنامم اضافه میشه و اگر هم که استفاده بشه اینجوری میشه.)
در ضمن در مورد کلید اصلی چی کار کنم( من پایگاه نداشتم به خاطر همین مشکل دارم)؟

محمدامین شریفی
جمعه 02 مرداد 1388, 22:46 عصر
بله شما درست می فرمایید با این که دارم سعی می کنم اشتباه نکنم ولی مثل اینکه ترک عادت موجب مرض است. به خاطر این اشتباه از همه عذر می خواهم.
حالا چی کار میشه کرد ، بد جوری گیرم ، هر چی فکر می کنم راهی به ذهنم نمیرسه(اگر بخوام از این رویداد استفاده نکنم کلی خط به برنامم اضافه میشه و اگر هم که استفاده بشه اینجوری میشه.)
در ضمن در مورد کلید اصلی چی کار کنم( من پایگاه نداشتم به خاطر همین مشکل دارم)؟
دوست من،اگر auto number کارایی حرفه ای داشت حتما در SQL می آمد.
auto number یک متغییر نسبی و نامعینی هست و اصولا مرتبط کردن آن با پایگاه داده صحیح نیست.
شما فیلد ID را کلید اصلی کن. و از auto number فقط در حالت design استفاده کن.
حتما فصل اول یک کتاب پایگاه داده را بخوان.
هنگام کار با پایگاه داده دیدت را فقط بر روی Winforms متمرکز نکن.شاید برنامه ات بعد ها بخواهد بر روی نت برود،پس اصول چند لایه ای را بیشتر رعایت کن.

پیروز باشید.

asefy2008
جمعه 02 مرداد 1388, 23:09 عصر
نمی تونم فیلد ID رو کلید اصلی کنم چون اون فیلدی که در برنامم کلید اصلی نمی تونه تکراری باشه و با اون به جدول دیگه ای هم می رم.
گویا باید فیلد ID رو حذف کنم؟
میشه شماره ها رو تو rowHeader قرار داد منظورم این هست که اون جا دیگه تو loop نمی افته؟

محمدامین شریفی
شنبه 03 مرداد 1388, 05:27 صبح
میشه شماره ها رو تو rowHeader قرار داد منظورم این هست که اون جا دیگه تو loop نمی افته؟
یک فیلد به گرید ویو اظافه کن،ولی بایندش نکن.من اینکار را کردم و شماره ستون هم 6 شد.

mn_zandy63
شنبه 03 مرداد 1388, 14:23 عصر
این کد رو امتحان کن. شاید کارت راه بیافته.


private void table_1DataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
var max = 0;
for (int i = 0; i < table_1DataGridView.Rows.Count; i++)
{
if (Convert.ToInt32(table_1DataGridView[0, i].Value) > max && i != e.RowIndex)
max = Convert.ToInt32(table_1DataGridView[0, i].Value);
}
table_1DataGridView[0, e.RowIndex].Value = max + 1;
}

اگه نباید کدت توسط داوطلب تغییر کنه٬ چرا ‍‍readOnly نیست؟
اگه مهم نیست که حتماً پشت سر هم باشند ‍ID ها٬ چرا از AutoIncreamet استفاده نمیکنی؟ دوستی که گفتند استفاده نکن اگه ممکنه دلایلشون رو بگن که ما هم یاد بگیریم.
و دیگه اینکه بهتره ID ت کلید باشه٬ اگه فیلد Object نباید تکراری باشه از Constraint ها استفاده کن و دیگه اینکه لزوماً فیلدت نباید کلید باشه تا بتونی به جدول های دیگه برسی ازش.

موفق باشی

asefy2008
شنبه 03 مرداد 1388, 15:49 عصر
یک فیلد به گرید ویو اظافه کن،ولی بایندش نکن.من اینکار را کردم و شماره ستون هم 6 شد.
ممنون این کار رو می کنم و فکر هم کنم جواب بده.

اگه نباید کدت توسط داوطلب تغییر کنه٬ چرا ‍‍readOnly نیست؟
برنامه اصلی من خیلی حجمش زیاد بود و یه نمونه قرار دادم و باید بگم readOnly هست .

اگه مهم نیست که حتماً پشت سر هم باشند ‍ID ها٬ چرا از AutoIncreamet استفاده نمیکنی؟
حتما مهم هست چون کاربر داره میبینه و صورت خوشی نداره اگه بهم ریخته باشه.

دوستی که گفتند استفاده نکن اگه ممکنه دلایلشون رو بگن که ما هم یاد بگیریم.
اگه منظورتون این هست که چرا بهتره از ID استفاده نکنیم ؟ به خاطر کد اضافه ، صرف زمان و حافظه بیشتر و....
نباید در در دیتابیس از ID استفاده بشه (حالا که من هم درست فکر می کنم میبینم اصلا لزومی نداره از فیلد ID استفاده کنم.)البته این ها یه سری مواردی بود که من به ذهنم رسید و ممکنه درست هم نباشه ، دوستمون می تونند بیشتر توضیح بدن.
دوست من ممنون از کدی که لطف کردین ولی همون طور که قبلا گفته شد اون رویداد بهترین هست. من تقریبا تمام رویدادها رو امتحان کردم ولی هیچ کدوم جواب نداد (کد شما هم تقریبا همین کار رو انجام میده با تعداد خط بیشتر و هنگام حذف جوابگو نیست .)
بازهم تشکر از توجه شما

mn_zandy63
یک شنبه 04 مرداد 1388, 01:30 صبح
سلام دوست عزیز
خواهش میکنم.


اگه منظورتون این هست که چرا بهتره از ID استفاده نکنیم
خیر منظور من این بود که چرا نباید از AutoIncreament استفاده کرد.

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

موفق باشید.

mn_zandy63
یک شنبه 04 مرداد 1388, 02:16 صبح
خب بر اساس حدسم در پست قبل٬

من کد خودتون رو یک مقدار دست کاری کردم.
مشکل اون کد رو میدونید٬ مشکل اینجاست که بدون وقفه سلول ها در حال ریفرش شدن هستند. با هر بار ریفرش هر سلول دوباره event مربوط به ریفرش شدن صدا زده میشه.

در اینجا با هر بار ریفرش شدن یک سلول برای ۱ میلی ثانیه جلوی ریفرش شدن مجددش گرفته میشه.




//Time interval for sleep refresh operation of a cell.
private long sleepInterval = new TimeSpan(0,0,0,0,1).Ticks;

//List of rows and their next refresh time.
private Dictionary<int,long> dic = new Dictionary<int, long>();

private void table_1DataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
//Check if this is right cell to refresh.
//This limits refresh operation to just ID cells.
if (e.ColumnIndex == 0)
{

//Get if this is the first time that current cell is refreshing.
//If not, get time for next refresh of current cell from list.
long nextRefresh;
bool firstRefresh = !dic.TryGetValue(e.RowIndex, out nextRefresh);

//Check if refresh is permited in this time.
if (firstRefresh || nextRefresh < DateTime.Now.Ticks)
{
//Refresh current cell.
table_1DataGridView[0, e.RowIndex].Value = e.RowIndex + 1;

//Set next refresh time for current cell.
dic.Remove(e.RowIndex);
dic.Add(e.RowIndex, DateTime.Now.Ticks + sleepInterval);

}
}
}


در واقع با این کار٬ بعد از هر بار ریفرش یک سلول٬ به مدت یک میلی ثانیه به وسیله شرط دوم جلوی اجرای تابع گرفته میشه٬ و همین زمان کوتاه برای افتادن آبها از آسیاب کافی است :چشمک: بنابراین دیگه ریفرش اضافه نداریم.
اگه یک کانتر در این تابع بگذارید متوجه خواهید شد که این تابع فقط در زمان نیاز اجرا میشه و دیگه مثل قبل مدام در حال اجرا نیست.

asefy2008
یک شنبه 04 مرداد 1388, 12:08 عصر
خیر منظور من این بود که چرا نباید از AutoIncreament استفاده کرد.
چون وقتی یک سطر از میانه ها حذف بشه دوباره شماره ها به ترتیب مرتب نمیشه.

شما تصمیم دارید به عنوان یک شماره ردیف از این فیلد استفاده کنید؟؟؟
بله(ولی دوستمون نظرم رو عوض کرد)

در واقع با هر مرتب سازی در گرید هم این شماره ها باز به ترتیب از اول تا آخر قرار خواهند گرفت. این فیلد در نهایت در دیتابیس هم ذخیره میشه؟؟؟؟
در دیتابیس ذخیره میشد ولی اگر ذخیره هم نشه مشکلی پیش نمیاد(در واقع نشه بهتره ، من در دیتابیسم تغییراتی دادم و ستون مربوط به ID رو حذف کردم . ID رو در دیتاگرید قرار میدم ولی بایندش نمی کنم)

به این ترتیب شما در هربار باز کردن یک فرم احتمالاً همه اطلاعات موجود در گرید رو در دیتابیس ذخیره خواهید کرد چون اطلاعات شما همیشه تغییر میکنند. در صورتی که تعداد رکورد ها بالا بره احتمالاً به مشکل بر میخورید. این طور نیست؟
خیر همه رو ذخیره نمی کنم من اطلاعات رو از تکست باکس ها میگیرم و مستقیما در دیتابیس ذخیره می کنم(البته نه کاملا مستقیم) و از دیتا گرید برای نمایش به کاربر استفاده می کنم . من به تغییر در ستون id کاری ندارم .

محمدامین شریفی
یک شنبه 04 مرداد 1388, 22:27 عصر
دوستی که گفتند استفاده نکن اگه ممکنه دلایلشون رو بگن که ما هم یاد بگیریم.

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


اگه منظورتون این هست که چرا بهتره از ID استفاده نکنیم ؟ به خاطر کد اضافه ، صرف زمان و حافظه بیشتر و....
نباید در در دیتابیس از ID استفاده بشه (حالا که من هم درست فکر می کنم میبینم اصلا لزومی نداره از فیلد ID استفاده کنم.)البته این ها یه سری مواردی بود که من به ذهنم رسید و ممکنه درست هم نباشه ، دوستمون می تونند بیشتر توضیح بدن.

و جوابشون را خودتون در نقل قول زیر دادید:


اگه مهم نیست که حتماً پشت سر هم باشند ‍ID ها٬ چرا از AutoIncreamet استفاده نمیکنی؟ ...
و دیگه اینکه بهتره ID ت کلید باشه٬ اگه فیلد Object نباید تکراری باشه از Constraint ها استفاده کن و دیگه اینکه لزوماً فیلدت نباید کلید باشه تا بتونی به جدول های دیگه برسی ازش.
در واقع منظور من هم این بود که ID باید unique identifier باشد.و استفاده از auto numbers در sql,مانند همان کاری که در Access انجام می دهیم،کار مبتدی گونه ای هست.
علی جان،اتفقا کار خوبی کردی که از ID استفاده کردی،
ولي بجاي شماره بي معني , بارکد و یا ترکیب چند فیلد،ID را با ان مقدار دهی كن.
auto numbers رافقط نمايشي به كاربر نشان بده.

auto numbers هم اتفاقا برای اینکار مناسب است.به چند دلیل:
1)لیست مرتب شده محصولات موجود در انبار
2)مرتب کردن داده ها با توجه به قیمت،نام الفبایی کالا و غیره
و دلایل دیگر.

اما نکته ای که قابل ذکر است،اینکه auto numbers را bind نکن.

پیروز باشید.

mn_zandy63
دوشنبه 05 مرداد 1388, 00:48 صبح
موفق باشی دوست عزیز
خوشحالم که مشکلت حل شد.

ممنون از توضیحاتت امین جان
البته من منظورم این جمله بود

دوست من،اگر auto number کارایی حرفه ای داشت حتما در SQL می آمد.
برای من جای سوال داره٬ البته فقط برای بالا رفتن اطلاعاتمون سوال میکنم.
فکر میکنم در این مورد اشتباه میکنید.
اگه اشتباه نکنم بخصوص وقتی که ایندکس روی یک فیلد داریم بهتره همیشه اون فیلد بصورت صعودی پر شه تا در نتیجهء مرتب سازی که SQL باید انجام بده روی اون ایندکس تاثیری نذاره٬ که حداکثر کارایی رو داشته باشیم به همین دلیله که فیلد های AutoIncreament کارایی خیلی خوبی دارن به خصوص وقتی ایندکس شده اند٬ البته در صورتی که محدودیتهای پروژه اجازه استفاده از اونها رو بهمون بدهند.
اگه اشتباه میکنم اصلاح کنید.

محمدامین شریفی
دوشنبه 05 مرداد 1388, 10:12 صبح
فکر میکنم در این مورد اشتباه میکنید.
اگه اشتباه نکنم بخصوص وقتی که ایندکس روی یک فیلد داریم بهتره همیشه اون فیلد بصورت صعودی پر شه تا در نتیجهء مرتب سازی که SQL باید انجام بده روی اون ایندکس تاثیری نذاره٬ که حداکثر کارایی رو داشته باشیم به همین دلیله که فیلد های AutoIncreament کارایی خیلی خوبی دارن به خصوص وقتی ایندکس شده اند٬ البته در صورتی که محدودیتهای پروژه اجازه استفاده از اونها رو بهمون بدهند.
اگه اشتباه میکنم اصلاح کنید.
هنگام relatonship داده, AutoIncreament بی معنی بنظر نمي اید؟دوما بنظر نمی اید, کارایی در پست 15 فاکتور مهمی در نظر گرفته شده باشد.به نظر شما AutoIncreament در چند برنامه تجاری می تواند مفید باشد؟ در قسمت بهينه شدن ذخیره سازی با شما موافقم ولی در عمل می توانید چند برنامه نام ببرید که از این روش, ID را مقدار دهی كرده باشند؟
اگه اشتباه میکنم اصلاح کنید.

ممنون,

محمدامین شریفی
دوشنبه 05 مرداد 1388, 21:56 عصر
موفق باشی دوست عزیز
خوشحالم که مشکلت حل شد.

ممنون از توضیحاتت امین جان
البته من منظورم این جمله بود

برای من جای سوال داره٬ البته فقط برای بالا رفتن اطلاعاتمون سوال میکنم.
فکر میکنم در این مورد اشتباه میکنید.
اگه اشتباه نکنم بخصوص وقتی که ایندکس روی یک فیلد داریم بهتره همیشه اون فیلد بصورت صعودی پر شه تا در نتیجهء مرتب سازی که SQL باید انجام بده روی اون ایندکس تاثیری نذاره٬ که حداکثر کارایی رو داشته باشیم به همین دلیله که فیلد های AutoIncreament کارایی خیلی خوبی دارن به خصوص وقتی ایندکس شده اند٬ البته در صورتی که محدودیتهای پروژه اجازه استفاده از اونها رو بهمون بدهند.
اگه اشتباه میکنم اصلاح کنید.
امروز به این متن در کتاب طراحی پرتال برخوردم:

A clustered index is used on fields that increase continuously, e.g., auto number

integer fields. Because SQL Server physically arranges rows in the database file
based on a clustered index field, if I choose some fields that do not continuously
increase, it will be rearrange too many pages during the INSERT and DELETE
steps.
• Foreign key fields are nonclustered index types because they are not added as
increasing values.
به نظر شما در اینگونه برنامه ها ID را چگونه در نظر بگیریم؟,فرض کنید خرید اینترنتی هم به قابلیت های این نرم افزاراضافه شد.

ممنون,