PDA

View Full Version : آموزش: نحوه ورق زدن منبع داده به زبان ساده برای مبتدیان



hobab-theme
دوشنبه 30 آذر 1388, 02:00 صبح
سلام دوستان
ممکنه عنوان کمی تکراری به نظر بیاد .
درسته کم و بیش در رابطه با پیاده سازی مکانیسم ورق زدن منبع صحبت شده ولی این موضوع جدید رو ایجاد کردم تا مختص این بحث قرار بگیره . امیدوارم مورد استفاده دوستان قرار بگیره .

تگهای مربوط به این آموزش : ورق زدن منبع داده ، مکانیسم ورق زدن
-------------------------
شروع ...
ورق زدن منبع داده (قسمت اول)

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



صفحه نمونه زیر حاوی یک کنترل ObjectDataSource هست که ورق زدن منبع داده اون فعال شده است :



<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Show Data Source Paging</title>
</head>
<body>
<form id="form1" runat="server">
<div>


<asp:GridView
ID="grdNews"
runat="server"
AllowPaging="True"
PageSize="4"
DataSourceID="srcNews"
CellPadding="5" />


<asp:ObjectDataSource
id="srcNews"
TypeName="NewsDSPaging"
SelectMethod="GetNews"
SelectCountMethod="GetNewsCount"
EnablePaging="True"
Runat="server" />
</div>
</form>
</body>
</html>




ملاحظه می کنید که کنترل ObjectDataSource دارای خاصیت EnablePaging است که با True مقدار دهی شده . همچنین ObjectDataSource دارای خاصیتی بنام selectCountMethod است . این خاصیت نام متدی که شماره یک رکورد از منبع داده بازیابی و ارائه میده .
علاوه بر این ملاحظه می کنید که کنترل GridView دارای خاصیتهای AllowPaging و PageSize هست . حتی وقتی که می خواید از ورق زدن منبع استفاده کنید باید خاصیت AllowPaging رو برای GridView فعال کنید تا GridView بتونه واسط ورق زدن خودش رو نمایش بده .
وقتی که خاصیت EnablePaging را برای یک کنترل ObjectDataSource با True مقدار دهی می کنید ، اون ObjectDataSource هنگام فراخوانی متد ارائه شده توسط خاصیت SelectMethod آن ، پارامترهای اضافی را منتقل می کنه . دو پارامتر اضافی ، StartRowIndex و MaximumRows نام دارند .
کنترل ObjectDataSource در صفحه ی محتوای بالا ، یک کامپوننت بنام NewsDSPaging ( مخفف News Data Source Paging ) را ارائه می کند .این کنترل ، متدهای GetNews() و GetNewsCount() کامپوننت را فراخوانی می کند . کامپوننت NewsDSPaging به صورت زیر می باشد :


Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Web.Configuration
Public Class NewsDSPaging
Private Shared ReadOnly _conString As String
''' <summary>
''' متدی برای ارسال پارامترهای مورد نیاز و بازیابی یک صفحه خاص از پایگاه داده
''' </summary>
''' <param name="startRowIndex"></param>
''' <param name="maximumRows"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function GetNews(ByVal startRowIndex As Integer, ByVal maximumRows As Integer) As SqlDataReader
' Initialize connection
Dim con As SqlConnection = New SqlConnection(_conString)
' Initialize command
Dim cmd As SqlCommand = New SqlCommand()
cmd.Connection = con
cmd.CommandText = "GetPagedNews"
cmd.CommandType = CommandType.StoredProcedure
' Add ADO.NET parameters
cmd.Parameters.AddWithValue("@StartRowIndex", startRowIndex)
cmd.Parameters.AddWithValue("@MaximumRows", maximumRows)
' Execute command
con.Open()
Return cmd.ExecuteReader(CommandBehavior.CloseConnection)
End Function
''' <summary>
''' متدی برای دریافت تعداد کل رکوردها از حافظه سرور
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function GetNewsCount() As Integer
Dim context As HttpContext = HttpContext.Current
If context.Cache("NewsCount") Is Nothing Then
context.Cache("NewsCount") = GetNewsCountFromDB()
End If
Return CType(context.Cache("NewsCount"), Integer)
End Function
''' <summary>
''' متدی برای بازیابی تعداد کل رکوردها از پایگاه داده
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Private Shared Function GetNewsCountFromDB() As Integer
Dim result As Integer = 0
' Initialize connection
Dim con As SqlConnection = New SqlConnection(_conString)
' Initialize command
Dim cmd As SqlCommand = New SqlCommand()
cmd.Connection = con
cmd.CommandText = "SELECT Count(*) FROM News"
' Execute command
Using con
con.Open()
result = CType(cmd.ExecuteScalar(), Integer)
End Using
Return result
End Function

Shared Sub New()
_conString = "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirector y|\Database.mdf;Integrated Security=True;User Instance=True"
End Sub
End Class




برای بهبود کارایی ، متد GetNewsCount() اقدام به گرفتن تعداد کل رکوردهای فیلم از Cache سرور می کنه . اگر تعداد رکوردها رو نتونه از کش بگیره ، اونو از پایگاه داده بازیابی می کنه توسط متد GetNewsCountFromDB() . این متد زمانی که متد GetNewsCount() نتونه مقدار NewsCount رو از کش پیدا کنه و بخونه فراخوانی میشه .
متد GetNews() برای بازیابی یک صفحه خاص از اخبار ، یک روال ذخیره شده ( SP ) بنام GetPagedNews را فراخوانی می کنه . پارامترهای StartRows و MaximumRows به روال منتقل می شن . رول ذخیره شده GetPagedNews به صورت زیر نوشته شده :


cREATE PROCEDURE dbo.GetPagedNews
(
@StartRowIndex INT,
@MaximumRows INT
)
AS
-- Create a temp table to store the select results
CREATE TABLE #PageIndex
(
IndexId INT IDENTITY (1, 1) NOT NULL,
RecordId INT
)
-- INSERT into the temp table
INSERT INTO #PageIndex (RecordId)
SELECT NewsID FROM News
-- Get a page of News
SELECT
NewsID,
NewsTitle,
NewsNote
FROM
News
INNER JOIN #PageIndex WITH (nolock)
ON News.NewsID = #PageIndex.RecordId
WHERE
#PageIndex.IndexID > @startRowIndex
AND #PageIndex.IndexID < (@startRowIndex + @maximumRows + 1)
ORDER BY
#PageIndex.IndexID




روال ذخیره شده GetPagedNews یک صفحه از رکوردهای پایگاه داده را بر میگردونه . روال ذخیره شده یک جدول موقتی بنام #PageIndex ایجاد می کنه که حاوی دو ستون است :
ستون Identity و ستونی که حاوی مقادیر کلید اولیه بدست آمده از جدول News پایگاه داده است . این جدول موقتی ، خانه هایی در ستون کلید اولیه که ممکن است با حذف رکوردها خالی شوند رو پر می کنه .
سپس این روال محدوده معینی از رکوردها رو از جدول #PageIndex بازیابی می کنه و نتایج رو به جدول News پایگاه داده الحاق می کنه . نتیجه نهایی این هست که فقط یک صفحه از پایگاه داده برگردانده می شه .
وقتی که صفحه محتوای ذکر شده رو باز می کنید ، GridView واسط ورق زدن خودش رو نشون میده که با استفاده از اون می تونید بین صفحات مختلف رکوردها رفت و برگشت کنید ...
-------------------------------------------------------------
-------------------------------------------------------------
توجه :
مکانیسم ورق زدنی که در این قسمت توضیح داده شد بر اساس مکانیسمی کار می کنه که توسط همایش های ( انجمن یا فروم ) Microsoft ASP.NET در http:www.ASP.NET.forums (http://www.ASP.NET.forums) و همایش های XBOX در http://www.xbox.com (http://www.xbox.com/) مورد استفاده قرار می گیرد . هر دو این سایتهای وب تعداد بیشماری از پیغام های ارسالی را هر روزه اداره می کنند . نرم افزار این همایش ها با ASP.NET نوشته شده و بعنوان جزئی از محصول Community Server از طریقTelligentSystems (www.telligentsystems.com (http://www.telligentsystems.com/)) قابل دسترسی است .
-------------------------------------------------------------
-------------------------------------------------------------

خوب دوستان امیدوارم بدردتون بخوره . مخصوصاً عزیزانی که تو این زمینه مبتدی هستن و تجربه کافی ندارن
یه نمونه از پروژه رو هم ضمیمه آموزش کردم واسه بررسی دقیق تر کدها
-----------------------------
منتظر قسمت دوم آموزش باشید
موفق و پیروز باشید:قلب:

Alireza_Salehi
دوشنبه 30 آذر 1388, 10:23 صبح
مقاله خوبی بود،
ولی توجه تون رو به این مقاله جلب میکنم، حتما خودتون اشکال کار رو متوجه میشید:
http://www.codeproject.com/KB/aspnet/PagingLarge.aspx

hobab-theme
سه شنبه 01 دی 1388, 01:06 صبح
ممنون از توجه تون

مقاله خوبی بود،
ولی توجه تون رو به این مقاله جلب میکنم، حتما خودتون اشکال کار رو متوجه میشید:
http://www.codeproject.com/KB/aspnet/PagingLarge.aspx (http://www.codeproject.com/KB/aspnet/PagingLarge.aspx)
توی این مقاله چند تا روش رو با هم مقایسه کرده و فکر میکنم نظر شما در مورد ایراد این نمونه کد استفاده از جداول موقت باشه ؟!
توی قسمت دوم مقاله به این موضوع می پردازیم و از تابع جدید ROW_NUMBET استفاده می کنیم
موفق باشید

hobab-theme
سه شنبه 01 دی 1388, 23:49 عصر
سلام دوستان
همون طور که توی پست قبلی گفتم و دوست خوبم جناب arsp_2004 هم اشاره کردن روش فوق الذکر یه مشکل داره . اون هم اینه که از جداول موقتی استفاده می کنه
خوب تو این پست می خوایم روش ذکر شده رو کمی توسعه بدیم و بهینه تر کنیم
برای این منظور ما از تابع جدید ()ROW_NUMBET استفاده می کنیم
این تابع به طور خودکار شماره ترتیبی یک سطر رو در داخل یک مجموعه نتیجه محاسبه می کنه .
خوب نمونه ای که تو پست اول گذاشتم رو به این صورت تغییر بدید ( روال زیر رو هم به روالها اضاف کنید )


CREATE PROCEDURE dbo.GetNewPagedNews
(
@StartRowIndex INT,
@MaximumRows INT
)
AS
WITH OrderedNews AS
(
SELECT
NewsID,
ROW_NUMBER() OVER (ORDER BY NewsID) AS RowNumber
FROM News
)

SELECT
OrderedNews.RowNumber,
News.NewsID,
News.NewsTitle,
News.NewsNote
FROM
OrderedNews
JOIN News
ON OrderedNews.NewsID = News.NewsID
WHERE
RowNumber BETWEEN (@StartRowIndex + 1) AND (@startRowIndex + @maximumRows + 1)

خوب همون طور که میبینید تو این روال دیگه از جداول موقتی خبری نیست و میتونید با خیال راحت استفاده کنید . همچنین بازده این از روال قبلی بیشتره .
بقیه کلاسها و توابع و صفحه محتوا هم که همون قبلی هست . هیچ فرقی نمیکنه . فقط یادتون نره که توی تابع GetNews از کلاس NewsDSPaging نام روال رو به نام روال جدید تغییر بدید
یعنی این قسمت :

cmd.Connection = con
cmd.CommandText = "GetPagedNews"
cmd.CommandType = CommandType.StoredProcedure
میشه این :


cmd.Connection = con
cmd.CommandText = "نام روال جدید"
cmd.CommandType = CommandType.StoredProcedure


موفق باشید

mehdi-ghafari
چهارشنبه 29 دی 1389, 11:46 صبح
سلام
ممنون از کد خوبتون
من از کد شما استفاده کردم عالی کار میکنه فقط نمی تونم ترتیب چیدمان اون رو در گریدویو تنظیم کنم
از متد order by id desc توی پروسودور هم استفاده کردم نشد

لطفاً من رو راهنمایی کنید خیلی کارم گیره
ممنون از شما

hobab-theme
چهارشنبه 29 دی 1389, 13:06 عصر
این رو


SELECT
NewsID,
ROW_NUMBER() OVER (ORDER BY NewsID) AS RowNumber
FROM News
)

به این تبدیل کنید


SELECT
NewsID,
ROW_NUMBER() OVER (ORDER BY NewsID DESC) AS RowNumber
FROM News
)

موردی که تغییر کرده رو با قرمز نشون دادم
در واقع تابع order by رو باید بالاتر تعریف می کردید

موفق باشید