نمایش نتیجه جستجوی انجام شده روی دیتاست در دیتاگریدویو

سلام وقت به خیر
دوستان من دارم یک برنامه ویندوزی تحت شبکه می نویسم که داخلش یک بخش جستجو قرار دادم که عملیات جستجو رو به ازای ورود هر حرف در تکست باکس انجام میده :
PHP:
private void txtSearch_TextChanged(object sender, EventArgs e)
        {
Searching...
        }
در پروژه های گذشتم کوئری جستجو رو مستقیما روی دیتابیس اعمال می کردم و نتیجه رو در دیتاگریدویو نمایش میدادم
و چون برنامه تک کاربره بود، دفعات اتصال بالا به دیتابیس مشکلی ایجاد نمی کرد (به ازای ورود هر حرف توسط کاربر، یک بار اتصال به دیتابیس و اعمال کوئری جستجو)
اما خب همونطور که خودتون می دونید این تکنیک، از لحاظ فنی ارزش بسیار پایینی داره...
در پروژه ی جدیدم چون برنامه چند کاربره و تحت شبکه هست میخوام از روش اصولی تر که خواندن یک بار اطلاعات از دیتابیس و اعمال کوئری جستجو روی دیتاست هست استفاده کنم (دوستان اگر تکنیک بهتری مدنظرتون هست مطرح کنید لطفا)
اما مشکلم اینجاست که بعد از اعمال جستجو روی دیتاست و گرفتن نتیجه در یک آرایه ی رکورد، نمی تونم اون رو در دیتا گرید ویو نمایش بدم. از تکنیک های زیر استفاده کردم ولی به نتیجه نرسیدم
اول سعی کردم به صورت دستی یه جدول به دیتاست اضافه کنم و رکوردها رو به اون جدول اضافه کنم که نشد :


PHP:
private void txtSearch_TextChanged(object sender, EventArgs e)
        {
            DataRow[] resultRows = ds.Tables["tblVisitant"].Select("Name Like  '%S%' ");
            DataTable dt = new DataTable("tblSearch");
            dt = ds.Tables["tblVisitant"].Clone();
            ds.Tables.Add(dt);
            foreach (DataRow row in resultRows)
                ds.Tables["tblSearch"].Rows.Add(row);
            dgvMain.DataBindings.Clear();
            dgvMain.DataBindings.Add("DataSource", ds, "tblSearch");
        }
خطایی که در رابطه با کد بالا داد :

attachment.php




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


PHP:
private void txtSearch_TextChanged(object sender, EventArgs e)
        {
            DataRow[] resultRows = ds.Tables["tblVisitant"].Select("Name Like  '%س%' ");
            DataTable dt = new DataTable("tblSearch");
            dt = ds.Tables["tblVisitant"].Clone();
            foreach (DataRow row in resultRows)
                dt.Rows.Add(row);
            dgvMain.DataSource = dt;
        }
خطایی که در رابطه با کد بالا داد :


attachment.php




دوستان عزیز ممنون میشم در این رابطه من رو راهنمایی کنید و ایراد روش های بالا رو هم توضیح بدید
خیلی ممنون
 

the_king

مدیرکل انجمن
سلام وقت به خیر
دوستان من دارم یک برنامه ویندوزی تحت شبکه می نویسم که داخلش یک بخش جستجو قرار دادم که عملیات جستجو رو به ازای ورود هر حرف در تکست باکس انجام میده :
در پروژه های گذشتم کوئری جستجو رو مستقیما روی دیتابیس اعمال می کردم و نتیجه رو در دیتاگریدویو نمایش میدادم

و چون برنامه تک کاربره بود، دفعات اتصال بالا به دیتابیس مشکلی ایجاد نمی کرد (به ازای ورود هر حرف توسط کاربر، یک بار اتصال به دیتابیس و اعمال کوئری جستجو)
اما خب همونطور که خودتون می دونید این تکنیک، از لحاظ فنی ارزش بسیار پایینی داره...
در پروژه ی جدیدم چون برنامه چند کاربره و تحت شبکه هست میخوام از روش اصولی تر که خواندن یک بار اطلاعات از دیتابیس و اعمال کوئری جستجو روی دیتاست هست استفاده کنم (دوستان اگر تکنیک بهتری مدنظرتون هست مطرح کنید لطفا)
اما مشکلم اینجاست که بعد از اعمال جستجو روی دیتاست و گرفتن نتیجه در یک آرایه ی رکورد، نمی تونم اون رو در دیتا گرید ویو نمایش بدم. از تکنیک های زیر استفاده کردم ولی به نتیجه نرسیدم
اول سعی کردم به صورت دستی یه جدول به دیتاست اضافه کنم و رکوردها رو به اون جدول اضافه کنم که نشد :

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

دوستان عزیز ممنون میشم در این رابطه من رو راهنمایی کنید و ایراد روش های بالا رو هم توضیح بدید
خیلی ممنون

متاسفانه کد هایی که نوشتید رو نمی تونم تفسیر کنم، احتمالا اگر روی نحوه بکار گیری DataGridView ها مطالعه بیشتری بکنید دست تان در انتخاب روش های پیاده سازی بازتر میشه.
اگر شخصا بخواهم چنین کاری رو انجام دهم حداقل دو مورد رو در نظر می گیرم. مورد اول اینه که وقفه در اتصال و جستجوی پایگاه داده نباید روی تعامل کاربر با فرم و TextBox تاثیر بذاره،
ایندو حداقل باید در نخ های مجزا اجرا شوند تا کاربر بدون وقفه بتونه به تایپ کردن و تعامل اش با فرم ادامه بده، در همون زمانی که برنامه با پایگاه داده در حال تبادل اطلاعات ئه.
مورد دوم اینه که عموما کاربر وقتی در حال تایپ کردنه داره تازه نیازش رو وارد می کنه، در همون لحظه که کاراکتر های جدیدی رو می نویسه نیازی به جستجو نداره، بعد از اینکه مکث کرد و درخواست اش مشخص شد باید جستجو شروع بشه.

مشاهده پیوست QueryWhileUserTyping.zip

در این نمونه کد من مورد اول رو با استفاده از BackgroundWorker و مورد دوم رو با استفاده از Timer پیاده سازی کردم. به عنوان مثال 10000 رکورد با ارقام ایجاد میشه تا جستجو ارقامی روی آنها انجام بشه. دلیل انتخاب ارقام ساده بودن
ساختن رکورد های تصادفی ئه. اطلاعات می تونه هم از Dataset ای که قبلا در حافظه RAM کش شده جستجو بشه و یا هر بار برای دریافت اطلاعات بروز مجددا Fill بشه (مثلا با اتصال به پایگاه داده ها)

به دو نکته توجه داشته باشید، نکته اول اینه که وقتی داده ها زیاده، پر کردن DataGridView کلا فرایند سنگینی میشه، برای همین قرار دادن رکورد ها برای نمایش بصورت تدریجی و از طریق یک نخ مجزا توسط BackgroundWorker مدیریت میشه.
به همین دلیل سنگینی فرایند مزاحم تعامل کاربر با برنامه نمیشه. نکته دوم اینه که همچین کدی کامل و بی نقص نیست، فرضا ممکنه دو جستجو به دلیل معطلی با هم تداخل پیدا کنند، برای کامل شدن به موارد زیادی احتیاج داره که با توجه به کاربرد شما باید بهینه بشه.
 
متاسفانه کد هایی که نوشتید رو نمی تونم تفسیر کنم، احتمالا اگر روی نحوه بکار گیری DataGridView ها مطالعه بیشتری بکنید دست تان در انتخاب روش های پیاده سازی بازتر میشه.
اگر شخصا بخواهم چنین کاری رو انجام دهم حداقل دو مورد رو در نظر می گیرم. مورد اول اینه که وقفه در اتصال و جستجوی پایگاه داده نباید روی تعامل کاربر با فرم و TextBox تاثیر بذاره،
ایندو حداقل باید در نخ های مجزا اجرا شوند تا کاربر بدون وقفه بتونه به تایپ کردن و تعامل اش با فرم ادامه بده، در همون زمانی که برنامه با پایگاه داده در حال تبادل اطلاعات ئه.
مورد دوم اینه که عموما کاربر وقتی در حال تایپ کردنه داره تازه نیازش رو وارد می کنه، در همون لحظه که کاراکتر های جدیدی رو می نویسه نیازی به جستجو نداره، بعد از اینکه مکث کرد و درخواست اش مشخص شد باید جستجو شروع بشه.

مشاهده پیوست 111159

در این نمونه کد من مورد اول رو با استفاده از BackgroundWorker و مورد دوم رو با استفاده از Timer پیاده سازی کردم. به عنوان مثال 10000 رکورد با ارقام ایجاد میشه تا جستجو ارقامی روی آنها انجام بشه. دلیل انتخاب ارقام ساده بودن
ساختن رکورد های تصادفی ئه. اطلاعات می تونه هم از Dataset ای که قبلا در حافظه RAM کش شده جستجو بشه و یا هر بار برای دریافت اطلاعات بروز مجددا Fill بشه (مثلا با اتصال به پایگاه داده ها)

به دو نکته توجه داشته باشید، نکته اول اینه که وقتی داده ها زیاده، پر کردن DataGridView کلا فرایند سنگینی میشه، برای همین قرار دادن رکورد ها برای نمایش بصورت تدریجی و از طریق یک نخ مجزا توسط BackgroundWorker مدیریت میشه.
به همین دلیل سنگینی فرایند مزاحم تعامل کاربر با برنامه نمیشه. نکته دوم اینه که همچین کدی کامل و بی نقص نیست، فرضا ممکنه دو جستجو به دلیل معطلی با هم تداخل پیدا کنند، برای کامل شدن به موارد زیادی احتیاج داره که با توجه به کاربرد شما باید بهینه بشه.

ممنون از توضیح کاملتون
با توجه به راهنمایی های شما فکر نمی کنم جستجوی حرف به حرف کار عاقلانه ای باشه، چون در زمانی که دیتابیس سنگین باشه می تونه مشکل ساز باشه
بازم ممنون بابت وقتی که گذاشتین
 
سلام و وقت به خیر مجدد
پاسخ :
دوستان برنامه نویس زمانی که تصمیم دارید عملیات جستجو رو روی DataSet پیاده کنید و از اعمال Query به صورت مستقیم روی دیتابیس خودداری کنید( حالا به هر دلیلی)، بایستی بعد از اعمال شرط روی DataSet، نتیجه ذخیره شده در آرایه رکوردی رو به روش زیر وارد یک DataTable کنید تا قابل نمایش در DataGridView بشه :
PHP:
DataRow[] resultRow = ds.Tables["Table A"].Select("Name Like '%" +txtSearch.Text+ "%'");
DataTable dt = ds.Tables["Table B"].Clone();
foreach (DataRow row in resultRow)
    dt.ImportRow(row);
dataGridView1.DataSource = dt;
همچنین می تونید از Dataview هم استفاده کنید :
PHP:
DataView dv = new DataView(ds.Tables["Table A"]);
dv.RowFilter = "Name Like '%" + txtSearch.Text + "%'";
dataGridView1.DataSource = dv;
موفق باشید
 

جدیدترین ارسال ها

بالا