PDA

View Full Version : سوال: مشکل در Paging سمت سرور....؟!



hamid1988
پنج شنبه 05 آذر 1388, 08:27 صبح
با سلام!
میخام داده هام رو در سمت سرور فیلتر کنم و در دیتالیست بریزم (کد زیر)

SELECT Top 10 [CategoryID], [Title] ,[ImageUrl],[CategoryArticlesCount] From [Articles_Categories] ORDER BY [CategoryArticlesCount]حالا مشکل زمانی پیش میاد که میخام به 10 دیتای بعدی دسترسی پیدا کنم، از طرف دیگر چون داده ها بر اساس CategoryArticlesCount مرتب میشن (نه بر اساس CategoryID) نمیتونم از کوئری هایی مشابه زیر استفاده کنم!

SELECT [CategoryID], [Title] ,[ImageUrl],[CategoryArticlesCount] From [Articles_Categories] Where CategoryID Between 10 And 20 ORDER BY [CategoryArticlesCount]لطفاَ راه حل پیشنهاد بدین....
ممنون

mohammad.sakhidel
پنج شنبه 05 آذر 1388, 09:04 صبح
به نظر من اول همه رکورد هاتو واکشی کن (با هر کوئری که میخوای مثلاً Top 100) بعدش خاصیت PageSize گریدویو رو برابر عدد دلخواهت بگیر (تو این مثال 10) و توی رویداد PageIndexChanging گرید ویو کد زیر رو بنویس :

GridView1.PageIndex = e.NewPageIndex;
SqlDataSource1.SelectCommand = yourQuery;
GridView1.DataBind();

البته می تونی GridView رو با هر روشی که می خوای پر کنی و yourQuery در بالا همون کوئری هست که همه رکورداتو باهاش واکشی کردی.

hadi000333
پنج شنبه 05 آذر 1388, 09:42 صبح
سلام
مشکل شما بیشتر sql تا asp
فکر کنم با ROW_NUMBER مشکل شما حل شه
http://msdn.microsoft.com/en-us/library/ms186734.aspx

hamid1988
پنج شنبه 05 آذر 1388, 10:12 صبح
به نظر من اول همه رکورد هاتو واکشی کندر این صورت Paging تحت سرور معنای خودش رو از دست میده، من برای افزایش سرعت واکشی داده ها میخام از این روش استفاده کنم.

خاصیت PageSize گریدویو رو برابر عدد دلخواهت بگیربا GridView به خاطر داشتن PageIndex مشکلی ندارم، مشکل من با DataList هست که این خاصیت رو نداره.

hamid1988
پنج شنبه 05 آذر 1388, 19:01 عصر
http://msdn.microsoft.com/en-us/library/ms186734.aspx
دوست عزیز منکه از کدهای این لینک سر در نیاوردم!، اگه میشه لطفاَ یکم توضیح بدین...

Mostafa_Dindar
پنج شنبه 05 آذر 1388, 21:42 عصر
من Paging رو تو ديتابيس انجام ميدم به صورت زير :

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go


ALTER PROCEDURE [dbo].[spNews_SelectAllPaged]

@startRowIndex int = -1,
@maximumRows int = -1,

AS

SELECT
[Id],
,
[Body],
[Image],
[Source],
[InsertDate]
FROM
(SELECT [B]ROW_NUMBER() OVER (ORDER BY Id) AS Row,
[Id],
[Brief],
[Body],
[Image],
[Source],
[InsertDate]
FROM [dbo].[News]) AS ObjRows
WHERE
((Row between (@startRowIndex) AND @startRowIndex + @maximumRows - 1)
OR @startRowIndex = -1 OR @maximumRows = -1)

--endregion

همانطور كه در اين نمونه ميبينيد SP من دو تا پارامتر داره :
يكي startRowIndex كه ميگه از اين شماره ركورد شروع كن و دوم به تعداد maximumRows ركورد برگردون
مثلا اگه با پارامتر هاي 50 و 10 فراخواني بشه ركوردهاي 51 تا 60 رو برميگردونه .
در صورتي هم كه sp رو بدون پارامتر فراخواني كنيم همه ركوردها رو برميگردونه

hamid1988
پنج شنبه 05 آذر 1388, 22:40 عصر
همانطور كه در اين نمونه ميبينيد SP من دو تا پارامتر داره :
يكي startRowIndex كه ميگه از اين شماره ركورد شروع كن و دوم به تعداد maximumRows ركورد برگردون

دوست عزیز میشه کمی در مورد کدها مخصوصاَ در مورد ROW_NUMBER() OVER توضیح بدین؟

bahman_akbarzadeh
پنج شنبه 05 آذر 1388, 22:50 عصر
راه حلي كه Lastphoenix (http://barnamenevis.org/forum/member.php?u=122118) ميگه از لحاظ سرعت و بهينگي بهتره.
ولي اگه فقط ميخواي كارت راه بيوفته و اگه ديتاليستي كه گذاشتي، چند ستوني نيست و هر ركورد در يك سطره، مي توني يه گريد ويو با يه ستون ItemTemplate بزاري و از Edit template مثل ديتا ليست استفاده كني و صفحه بندي هم انجام بدي.

hamid1988
پنج شنبه 05 آذر 1388, 22:57 عصر
اگه ديتاليستي كه گذاشتي، چند ستوني نيست و هر ركورد در يك سطره
دیتالیست من چند ستونیه و برای Paging هم از یک کامپوننت دیگه استفاده می کنم (شبیه Paging همین سایت)...

A.S.Roma
پنج شنبه 05 آذر 1388, 23:10 عصر
دیتالیست را خیلی راحت میشه با ListView پیدا سازی کرد . هم قدرتمند تره هم منعطف تر هم اصولی تر . Paging هم داره

Mostafa_Dindar
جمعه 06 آذر 1388, 00:07 صبح
دوستان هميشه براي هر كاري راه حل هاي بسياري وجود داره ولي بايد با توجه به شرايط بهترين رو انتخاب كنيم .
ما در چند جا ميتونيم Paging رو پياده سازي كنيم :

يك روش ميتونه Client Side Paging باشه كه توسط جاوا اسكريپت اينكار رو ميكنيم .
اينجا چند تا نمونه هست كه ميتونيد دنبال كنيد :
Client-side Paging for DataGrids (http://msdn.microsoft.com/en-us/magazine/cc164022.aspx)
Client Side Table Sorting, Paging and Filtering with jQuery (http://beckelman.net/post/2008/10/23/Client-Side-Table-Sorting-Paging-and-Filtering-with-jQuery-Demo.aspx)

همچنين Paging ميتونه در Business Layer رخ بده . در اين حالت شما يك ليستي از آبجكتها رو از DataSource ميخوني و اونا رو Paging ميكني ( بايد خودتون اونو پياده سازي كنين )

همچنين اگه تعداد ركوردها كم باشه ميتونيم از DataSet استفاده كنيم . در صورت استفاده از DataSet ما ميتوانيم از ويژگيهاي Built-In داخل GridView و ListView براي Paging and Sorting استفاده كنيم . ولي همانطور كه ميدونيد در صورتي كه از DataSet استفاده كنيم عملا در ابتدا همه ركوردها واكشي ميشن و Paging ما يك جورايي مجازي است . سرعت كند ميشه . چون Paging واقعي نيست و شبيه سازي شده . البته ميتونيم از Caching استفاده كنيم كه باز هم در صورتي كه تعداد ركوردها كم باشه پيشنهاد ميشه .
فرض كنيد 1000 ركورد رو با DataSet برگردوندين درسته كه 10 تاي اول اونو نشون ميده ولي همه اين 1000 ركورد تو حافظه لود كرده .

روش بهينه در صورتي كه از تعداد ركوردها زياد باشه Paging در سطح ديتابيس هستش . در اين صورت تنها به تعداد مورد نظرمون ركورد برميگردونيم .

قبل از sql2005 كار براي Paging كمي مشكل بود ولي با ROW_NUMBER() در sql2005 كار خيلي ساده شد .
ولي نكته مهم اينه كه حالا كه ما در سطح DataBase عمل Paging رو انجام داديم چطور بايد از اون در UI استفاده كنيم . بعبارت ساده تر چطور اين Paging رو با GridView هماهنگ كنيم .
اول ازهمه GridView لازم داره بدونه تعداد كل ركوردها چند تاست . خوب من sp اي كه بالاتر گفتم رو ميتونم اينجوري هم بنويسم تا تعداد كل ركوردها رو هم داشته :

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go


ALTER PROCEDURE [dbo].[spNews_SelectAllPaged]

@startRowIndex int = -1,
@maximumRows int = -1,
@recordCount int = NULL OUTPUT

AS

IF (@recordCount IS NOT NULL)
BEGIN
SET @recordCount = (SELECT COUNT(*) FROM [dbo].[News] )
RETURN
END
SELECT
[Id],
[Brief],
[Body],
[Image],
[Source],
[InsertDate]
FROM
(SELECT ROW_NUMBER() OVER (ORDER BY Id) AS Row,
[Id],
[Brief],
[Body],
[Image],
[Source],
[InsertDate]
FROM [dbo].[News]) AS ObjRows
WHERE
((Row between (@startRowIndex) AND @startRowIndex + @maximumRows - 1)
OR @startRowIndex = -1 OR @maximumRows = -1)

--endregion

براي اطلاعات بيشتر ميتونيد اينجا رو مطالعه كنيد :
http://aspnet.4guysfromrolla.com/articles/031506-1.aspx

hamid1988
جمعه 06 آذر 1388, 00:36 صبح
دوست عزیز، کوئریم رو بصورت زیر نوشتم، جواب نداد!

SELECT [CategoryID], [Title] ,[ImageUrl],[CategoryArticlesCount]
From (Select ROW_NUMBER() OVER (ORDER BY [CategoryArticlesCount])
AS Row,[CategoryID], [Title] ,[ImageUrl],[CategoryArticlesCount]
From [Articles_Categories]) As ObjRows Where Row between 10 AND 20

Mostafa_Dindar
جمعه 06 آذر 1388, 00:55 صبح
دوست عزیز، کوئریم رو بصورت زیر نوشتم، جواب نداد!

SELECT [CategoryID], [Title] ,[ImageUrl],[CategoryArticlesCount]
From (Select ROW_NUMBER() OVER (ORDER BY [CategoryArticlesCount])
AS Row,[CategoryID], [Title] ,[ImageUrl],[CategoryArticlesCount]
From [Articles_Categories]) As ObjRows Where Row between 10 AND 20
يعني چي جواب نداد ؟ يعني خطاي Syntax گرفت ؟ كه بعيد ميدونم چون درست نوشتي .
ركورد برنميگردونه ؟ كه شايد ركورد نداري يا كمتر از 10 تا ركود داري !

hamid1988
جمعه 06 آذر 1388, 01:11 صبح
يعني چي جواب نداد ؟
دیتاهایی که بر میگردونه ORDER BY CategoryArticlesCount نیست!

hamid1988
جمعه 06 آذر 1388, 01:27 صبح
در واقع من دنبال راه حلی برای ترکیب دو کوئری زیر هستم:


1)SELECT *
From [Articles_Categories] ORDER BY [CategoryArticlesCount]

2)SELECT *
From [Articles_Categories] Where CategoryID between 10 and 20


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

Mostafa_Dindar
جمعه 06 آذر 1388, 08:49 صبح
SP كاملا درسته .
اينجا عكس چند تا كوئري رو ميزارم كه كاملا درست كار كرده .
اگه بازم مشكل داشتي خصوصي به من پيام بده .


http://barnamenevis.org/forum/attachment.php?attachmentid=40393&stc=1&d=1259300725

http://barnamenevis.org/forum/attachment.php?attachmentid=40394&stc=1&d=1259300725






http://barnamenevis.org/forum/attachment.php?attachmentid=40395&stc=1&d=1259300725
http://barnamenevis.org/forum/attachment.php?attachmentid=40396&stc=1&d=1259300725

hamid1988
جمعه 06 آذر 1388, 09:35 صبح
دوست عزیز دستتون درد نکنه، کارم راه افتاد!
اگه میشه در مورد کدهای زیر هم یه توضیحی بدین...

FROM
(SELECT ROW_NUMBER() OVER (ORDER BY Id) AS Row,
[Id],
[Brief],
[Body],
[Image],
[Source],
[InsertDate]
FROM [dbo].[News]) AS ObjRows

Mostafa_Dindar
جمعه 06 آذر 1388, 13:06 عصر
http://msdn.microsoft.com/en-us/library/ms186734.aspx

مثالهاش كاملا گوياست

emad8159
دوشنبه 09 آذر 1388, 07:51 صبح
سلام دوستان عزیز

فکر کنم تنها چیزی که بتونه مشکل شما رو حل کنه استفاده از کنترل ObjectDataSource

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


موفق باشید:لبخندساده: