http://www.tabatabaei.info/csharpsamples/CSharpTutorial.pdf
فیلم های آموزشی مایکروسافت برای کسانی که می خواهند برنامه نویسی با ابزارهای مایکروسافت را بیاموزند:
حالا يه صفحه اي كه اين Pager رو تو خودش داره. يه DropDownList هم اضافه كردم كه كاربر بتونه تعداد ركوردهاي هر صفحه رو انتخاب كنه. اينجا از Event ي كه تعريف كرده بوديم براي نمايش شماره صفحه اي كه كاربر داره روش كليك مي كنه استفاده مي كنيم. يه تابع داريم كه اطلاعات رو از بانك اطلاعاتي بارگذاري مي كنه. مي تونيد به اين تابع شماره صفحه و تعداد ركورد و فيلتر و فيلدي براي مرتب سازي داده ها هم ارسال كنيد.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Assembly="FanaCustomControls" Namespace="FanaCustomControls" TagPrefix="fcc" %>
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>Untitled Pagetitle>
head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblMessage" runat="server">asp:Label><br />
<asp:DropDownList ID="ddlPageSize" runat="server">
<asp:ListItem>10asp:ListItem>
<asp:ListItem>20asp:ListItem>
<asp:ListItem>100asp:ListItem>
asp:DropDownList>
<fcc:DataPaging ID="DataPaging1" runat="server" />
div>
form>
body>
html>
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
DataPaging1.SelectedPageChanged += new EventHandler(SelectedPageChanged);
DataPaging1.PageSize = Convert.ToInt32(ddlPageSize.SelectedValue);
int RecordCount = 0;
//RecordCount=SELECT * FROM Table WHERE Condition
DataPaging1.RecordCount = RecordCount;
ViewState["RecordCount"] = RecordCount;
BindDataList(1, Convert.ToInt32(ddlPageSize.SelectedValue), "Date", "[Name] LIKE '%hh%'");
}
catch (Exception exp)
{
lblMessage.Text = exp.Message;
}
}
protected void SelectedPageChanged(object sender, EventArgs e)
{
Response.Write(string.Format("شما در حال مشاهده صفحه {0} هستید", DataPaging1.PageIndex.ToString()));
BindDataList(DataPaging1.PageIndex, Convert.ToInt32(ddlPageSize.SelectedValue), "Date", "[Id]>0");
}
private void BindDataList(int pageIndex, int pageSize, string sortField, string filterString)
{
try
{
string _ConnectionString = "";
SqlConnection connection = new SqlConnection(_ConnectionString);
SqlCommand command = new SqlCommand();
command.Connection = connection;
//You should bind your datalist to database here using a query like this
string query = "SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY @SortField) AS RowNum, [Field1], [Field2] FROM [TableName] WHERE @FilterString) AS MainQuery WHERE RowNum>=@StartRecord AND RowNum<@EndRecord ";
command.CommandText = query;
command.Parameters.AddWithValue("@SortField", sortField);
command.Parameters.AddWithValue("@FilterString", filterString);
int startRecord = Convert.ToInt32(ViewState["RecordCount"]) / pageSize * pageIndex;
int endRecord = startRecord + pageSize;
command.Parameters.AddWithValue("@StartRecord", startRecord);
command.Parameters.AddWithValue("@EndRecord", sortField);
connection.Open();
SqlDataReader dataReader;
dataReader = command.ExecuteReader();
while (dataReader.Read())
{
//Enter Records In a ArrayList, DataTable Or Dataset
}
connection.Close();
}
catch (Exception exp)
{
lblMessage.Text=exp.Message;
}
}
}
چند تا كد آماده ديدم كه اين كار رو انجام دادن اما اكثرا اطلاعات رو از بانك اطلاعاتي Load مي كنن و صفحه بندي اطلاعات رو توي Presentation layer يا Data Access Layer انجام مي دن. اما قابليتي كه SQLSERVER 2005 داره اين امكان رو مي ده كه فقط ركورد هايي رو كه مي خوايم به كاربر نمايش بديم رو Load كنيم. اين جوري Performance كار خيلي بالا مي ره.
براي اينكه بتونيم يه Data Paging محكمه پسند ارائه بديم چند تا كار بايد بكنيم. اول يه مثال از دستوري كه Paging داده ها رو انجام ميده مي زنم كه ببينيد sql server اين امكان رو چطوري پشتيباني مي كنه.
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY [Id]) AS RowNum, [Field1], [Field2] FROM [TableName] WHERE [Name]='Fana') AS MainQuery WHERE RowNum>=10 AND RowNum<20
با يه همچين كدي مي تونيد ركوردهاي 10 تا 20 رو از بانك اطلاعاتي Load كنيد. براي اينكه بتونيد به تعداد صفحات اطلاعات براي كاربر لينك بزاريد، توصيه مي كنم يه كنترل درست كنيد كه اين كار رو براتون انجام بده. با استفاده از ويژوال استوديو مي تونيد يه Web Custom Control درست كنيد كه برنامه نويس فقط تعداد ركوردها رو بش پاس بده و نگران بقيه قسمت هاي كار نباشه. كد يه Custom Control رو اينجا آوردم كه با همون شرايطي كه نوشتم كار مي كنه. درضمن يه Event هم بش اضافه كردم كه برنامه نويس مي تونه تشخيص بده كاربر درخواست يه Page جديد داشته يانه؟ اين كنترل 5تا لينك رو نمايش مي ده (Section 1) و با كليك كاربر بر روي لينك صفحه پنجم، اين 5تا لينك، شماره هاشون تبديل به 3 تا 7 مي شه(Section2) اين طوري كاربر هميشه 5 تا لينك توي صفحه داره كه هرچقدر جلو بريم شماره هاي لينك ها افزايش پيدا مي كنه
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
[assembly:TagPrefix("FanaCustomControls","fcc")]
namespace FanaCustomControls
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:DataPaging runat=server>{0}:DataPaging>")]
public class DataPaging : WebControl
{
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
#region Properties
private int _SectionIndex = 1;
private int _SectionCount = 1;
private int _PageSize = 10;
///
/// تعداد رکوردهای هر صفحه. به صورت پیش فرض هر صفحه 10 رکورد را نمایش می دهد
///
public int PageSize
{
get { return _PageSize; }
set { _PageSize = value; }
}
private long _RecordCount;
///
/// تعداد کل رکوردهایی که قرار است صفحه بندی شوند
///
public long RecordCount
{
get { return _RecordCount; }
set
{
_RecordCount = value;
//تعیین تعداد صفحات
PageCount = (int)value / _PageSize + 1;
}
}
private int _PageCount;
///
/// تعداد کل صفحات
///
public int PageCount
{
get { return _PageCount; }
set
{
_PageCount = value;
int counter = 5;
_SectionCount = 1;
while (counter < value)
{
counter += 2;
_SectionCount++;
}
CreateChildControls();
}
}
private int _PageIndex = 1;
///
/// شماره صفحه جاری
///
public int PageIndex
{
get { return _PageIndex; }
set { _PageIndex = value; }
}
#endregion
#region ControlsOnTheForm
private LinkButton lnkBtn1;
private LinkButton lnkBtn2;
private LinkButton lnkBtn3;
private LinkButton lnkBtn4;
private LinkButton lnkBtn5;
#endregion
#region Events_Methods
public EventHandler SelectedPageChanged;
public void OnBtn1Click(Object o, System.EventArgs ea)
{
try
{
_PageIndex = Convert.ToInt32(lnkBtn1.Text);
if (_SectionIndex > 1)
{
ReduceSectionIndex();
}
if (SelectedPageChanged != null)
{
SelectedPageChanged(this, EventArgs.Empty);
}
}
catch
{
throw;
}
}
public void OnBtn2Click(Object o, System.EventArgs ea)
{
try
{
_PageIndex = Convert.ToInt32(lnkBtn2.Text);
if (SelectedPageChanged != null)
{
SelectedPageChanged(this, EventArgs.Empty);
}
}
catch
{
throw;
}
}
public void OnBtn3Click(Object o, System.EventArgs ea)
{
try
{
_PageIndex = Convert.ToInt32(lnkBtn3.Text);
if (SelectedPageChanged != null)
{
SelectedPageChanged(this, EventArgs.Empty);
}
}
catch
{
throw;
}
}
public void OnBtn4Click(Object o, System.EventArgs ea)
{
try
{
_PageIndex = Convert.ToInt32(lnkBtn4.Text);
if (SelectedPageChanged != null)
{
SelectedPageChanged(this, EventArgs.Empty);
}
}
catch
{
throw;
}
}
public void OnBtn5Click(Object o, System.EventArgs ea)
{
try
{
_PageIndex = Convert.ToInt32(lnkBtn5.Text);
if (_SectionCount > _SectionIndex)
{
AddSectionIndex();
}
if (SelectedPageChanged != null)
{
SelectedPageChanged(this, EventArgs.Empty);
}
}
catch
{
throw;
}
}
public void AddPageIndex(int count)
{
try
{
_PageIndex += count;
int Start = _SectionIndex + _SectionIndex - 1;
if (_PageIndex == Start)
{
ReduceSectionIndex();
}
if (_PageIndex == Start + 4)
{
AddSectionIndex();
}
}
catch
{
throw;
}
}
public void ReducePageIndex(int count)
{
try
{
_PageIndex -= count;
int Start = _SectionIndex + _SectionIndex - 1;
if (_PageIndex == Start)
{
ReduceSectionIndex();
}
if (_PageIndex == Start + 4)
{
AddSectionIndex();
}
}
catch
{
throw;
}
}
private void AddSectionIndex()
{
try
{
_SectionIndex += 1;
CreateChildControls();
}
catch
{
throw;
}
}
private void ReduceSectionIndex()
{
try
{
_SectionIndex -= 1;
CreateChildControls();
}
catch
{
throw;
}
}
#endregion
protected override void CreateChildControls()
{
base.CreateChildControls();
try
{
this.Controls.Clear();
//مدیریت دکمه های بعدی، قبلی، اولین و آخرین صفحه
int _Start = 1;
_Start = _SectionIndex + _SectionIndex - 1;
if (_Start > 1)
{
//imgBtnPrevious.Enabled = true;
//imgBtnFirst.Enabled = true;
}
if (_PageIndex < _PageCount)
{
//imgBtnLast.Enabled = true;
//imgBtnNext.Enabled = true;
}
if (_PageIndex > 1)
{
//imgBtnPrevious.Enabled = true;
}
//ایجاد لینک صفحات
if (_PageCount >= _SectionIndex + _SectionIndex - 1)
{
lnkBtn1 = new LinkButton();
lnkBtn1.Text = Convert.ToString(_SectionIndex + _SectionIndex - 1);
lnkBtn1.Click += new EventHandler(OnBtn1Click);
this.Controls.Add(lnkBtn1);
}
if (_PageCount >= _SectionIndex + _SectionIndex)
{
lnkBtn2 = new LinkButton();
lnkBtn2.Text = Convert.ToString(_SectionIndex + _SectionIndex);
lnkBtn2.Click += new EventHandler(OnBtn2Click);
this.Controls.Add(lnkBtn2);
}
if (_PageCount >= _SectionIndex + _SectionIndex + 1)
{
lnkBtn3 = new LinkButton();
lnkBtn3.Text = Convert.ToString(_SectionIndex + _SectionIndex + 1);
lnkBtn3.Click += new EventHandler(OnBtn3Click);
this.Controls.Add(lnkBtn3);
}
if (_PageCount >= _SectionIndex + _SectionIndex + 2)
{
lnkBtn4 = new LinkButton();
lnkBtn4.Text = Convert.ToString(_SectionIndex + _SectionIndex + 2);
lnkBtn4.Click += new EventHandler(OnBtn4Click);
this.Controls.Add(lnkBtn4);
}
if (_PageCount >= _SectionIndex + _SectionIndex + 3)
{
lnkBtn5 = new LinkButton();
lnkBtn5.Text = Convert.ToString(_SectionIndex + _SectionIndex + 3);
lnkBtn5.Click += new EventHandler(OnBtn5Click);
this.Controls.Add(lnkBtn5);
}
}
catch
{
throw;
}
this.ChildControlsCreated = true;
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//Label lblMessage = new Label();
//lblMessage.Text = "صفحه شمار";
//this.Controls.Add(lblMessage);
this.EnsureChildControls();
}
}
}
تا اونجايي كه تونستم توي كد Comment گذاشتم. هرجاش كه مفهوم نبود و توضيح لازم داشت بگيد اضافه كنم
توی مطلب قبلی (عدم استفاده از DataSet قسمت سوم ) نوشته بودم که باید اطلاعات ConnectionString رو توی یه کلاس دیگه ذخیره کنیم. یه همچین کدی هم نوشته بودم
_connectionString = clsConfiguration.ConnectionString;
من همیشه یه کلاس ایجاد می کنم به اسم clsConfiguration که اطلاعات ConnectionString و پیکربندی های دیگه رو توش ذخیره می کنم. برا اینکه استفاده کردن از این متغیرها ساده باشه دو راه داریم. یا اینکه متغیر ها رو از نوع Static تعریف کنیم و یا اینکه Const باشن. اینطوری دیگه لازم نیست یه Instance از روی کلاس clsConfiguration بسازیم. کد کلاس مورد نظر اینطوریه
using System;
using System.Collections.Generic;
using System.Text;
namespace HamidDarabi
{
class clsConfiguration
{
public const string ConnectionString = "Data Source='ServerName';Initial Catalog=MyDataBaseName;UID='SQLServerUserName'; Password='SQLServerPassword'";
}
}
جابجا کردن بانک اطلاعاتی Sql Server به روش های مختلف. برای این کار چند روش جالب هست. برای دوتا از روش ها کد آماده کردم که کافیه توی یه Query Editor اجرا کنید.
برای جابجا کردن بانک اطلاعاتی از طریق Management studio کافیه روی بانک اطلاعاتی راست کلیک کنیم و گزینه Detach Database، و سرور مقصد روی گزینه Database راست کلیک کنید و گزینه Attach Databse رو انتخاب کنید. آدرس فایل رو هم با استفاده از دکمه Browse می تونید پیدا کنید.
اما جابجا کردن فایل بانک اطلاعاتی از طریق یک Query Editor:
1)اول باید بانک اطلاعاتی رو Detach کنیم از طریق یک Stored Procedure به نام sp_detach_db که توی بانک Master تعبیه شده.
2)فایل رو به محل جدید که معمولا یه کامپیوتر دیگه است منتقل می کنیم
3)با استفاده از دستور Create Database و دادن آدرس فایل های MdF و LDF و استفاده از کلمه کلیدی For Attach دوباره بانک اطلاعاتی رو به سرور جدید متصل می کنیم
مثال:
مرحله اول
USE master;GO EXEC sp_detach_db @dbname = 'darabiDB';GO مرحله دوم: فرض می کنیم فایل های MDF و LDF توی ریشه درایو I: هستند
USE master;GO
CREATE DATABASE darabiDB
ON (FILENAME = 'I:\darabiDB_Data.mdf'),
(FILENAME = 'I:\darabiDB_Log.ldf')
FOR ATTACH;
GO
اما مایکروسافت توصیه کرده که از دستور Alter استفاده کنیم. این دستور برا کار با Database و تغییرات توی فایل بانکه. توضیح این دستور خیلی مفصله. اگه می خواید بیشتر در موردش بدونید برید به این آدرس:
http://technet.microsoft.com/en-us/library/ms174269.aspx
اینجا فقط چند شکل مختلف دستور رو که برا کار ما مهمه می بینیم. مراحل جابجا کردن بانک به این ترتیبه:
1)فایل های بانک اطلاعاتی رو کپی کنید روی سیستم مقصد
2)یه بانک جدید روی سرور مقصد با همون اسم درست کنید. (یه Create Database ساده)
3)دستور زیر رو اجرا کنید
ALTER DATABASE darabiDB SET OFFLINE
4)دستور زیر رو اجرا کنید
ALTER DATABASE darabiDB MODIFY FILE ( NAME = darabiDB, FILENAME = 'آدرس فایل' )
5)دوباره بانک رو راه بندازیدALTER DATABASE darabiDB SET ONLINE
حمید دارابی
حالا برا دسترسی به جدول Company از بانک اطلاعاتی یه کلاس ایجاد می کنیم که من اسمشو Company گذاشتم. کد کاملا واضح و خواناست. اگه احیانا مشکلی داشتید یا جاییش مفهوم نبود خوشحال می شم مطلب رو کامل کنم.
using System;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Text;
namespace DAL
{
public class Company
{
#region Constructors
public Company()
{
//اطلاعات Connection رو باید توی یه کلاس دیگه وارد کرده باشید
_connectionString = clsConfiguration.ConnectionString;
this.ArlCompanySL = new ArrayList();
}
#endregion
#region Properties
private string _connectionString;
//برای داشتن لیستی از کمپانی ها از آرایه استفاده می کنیم
//چون دیتاست خیلی سربار اضافی داره
private ArrayList _arlCompanySL;
public ArrayList ArlCompanySL
{
get { return _arlCompanySL; }
set { _arlCompanySL = value; }
}
private long _Id;
public long Id
{
get { return _Id; }
set { _Id = value; }
}
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
#endregion
#region Methods
//لیستی از کمپانی ها رو توی یک آرایه می ریزه
public void FillMyList()
{
try
{
using (SqlConnection connection = new SqlConnection(_connectionString))
{
SqlCommand command = new SqlCommand("spCompanySLSelect", connection);
command.CommandType = CommandType.StoredProcedure;
SqlDataReader dr;
connection.Open();
//با استفاده از دیتا ریدر سربار کد رو کمتر می کنیم
dr = command.ExecuteReader();
while (dr.Read())
{
Company objCompanySD = new Company();
objCompanySD.Id = Convert.ToInt64(dr["Id"]);
objCompanySD.Name = Convert.ToString(dr["Name"]);
//با لود شدن هر رکورد اونو به آرایه اضافه می کنیم
this.ArlCompanySL.Add(objCompanySD);
}
dr.Close();
connection.Close();
}
}
catch (Exception exp)
{
throw;
}
}
//اطلاعات مربوط به یک رکورد(یک کمپانی)رو برمی گردونه
public void FillMyself()
{
try
{
using (SqlConnection connection = new SqlConnection(_connectionString))
{
SqlCommand command = new SqlCommand("spCompanySelect", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@Id", this._Id);
SqlDataReader dr;
connection.Open();
dr = command.ExecuteReader();
if (dr.Read())
{
this._Name = Convert.ToString(dr["Name"]);
}
dr.Close();
connection.Close();
}
}
catch (Exception exp)
{
throw;
}
}
public void UpdateMyself()
{
try
{
using (SqlConnection connection = new SqlConnection(_connectionString))
{
SqlCommand command = new SqlCommand("spCompanyUpdate", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@Id", this._Id);
command.Parameters.AddWithValue("@Name", this._Name);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
catch (Exception exp)
{
throw;
}
}
public void DeleteMyself()
{
try
{
using (SqlConnection connection = new SqlConnection(_connectionString))
{
SqlCommand command = new SqlCommand("spCompanyDelete", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@Id", this._Id);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
catch (Exception exp)
{
throw;
}
}
public void SaveMyself()
{
try
{
using (SqlConnection connection = new SqlConnection(_connectionString))
{
SqlCommand command = new SqlCommand("spCompanyInsert", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@Name", this._Name);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
catch (Exception exp)
{
throw;
}
}
#endregion
}
پایان قسمت سوم
یک جدول توی بانک اطلاعاتی ایجاد کنید که اسمش Company باشه. این جدول برای هر کمپانی نام(nvarchar 50) و کد(bigint) کمپانی رو ذخیره می کنه. فیلد Id باید Identity specification رو Yes کنید. کد تولید این جدول:
CREATE TABLE [Company] (
[Id] [bigint] IDENTITY (1, 1) NOT NULL ,
[Name] [nvarchar] (50) COLLATE Arabic_CI_AS NULL ,
CONSTRAINT [PK_Company] PRIMARY KEY CLUSTERED
(
[Id]
) ON [PRIMARY]
) ON [PRIMARY]
GO
5 تا Stored procedure ایجاد کنید که کارهای حذف، اضافه، ویرایش، انتخاب یک کمپانی و انتخاب همه کمپانی ها رو انجام بده. کد این Stored procedure ها رو اینجا براتون نوشتم:
CREATE PROC spCompanyDelete
@Id bigint
as
DELETE FROM [Company]
WHERE ([Company].[Id]=@Id)
GO
CREATE PROC spCompanyInsert
@Name nvarchar(50)
as
BEGIN
INSERT INTO [Company] (
[Name])
VALUES(
@Name)
END
GO
CREATE PROC spCompanySelect
@Id bigint
as
SELECT
[Company].[Id],
[Company].[Name]
FROM [Company]
WHERE ([Id]=@Id)
GO
CREATE PROC spCompanySLSelect
as
SELECT
[Company].[Id],
[Company].[Name]
FROM [Company]
GO
CREATE PROC spCompanyUpdate
@Id bigint,
@Name nvarchar(50)
as
Update [Company]
SET
[Company].[Name]=@Name
WHERE
([Company].[Id]=@Id)
GO
اگه از SQLServer 2005 استفاده نمی کنید، برا اجرای این کدها می تونید از نرم افزار Query analyzer استفاده کنید
پایان قسمت دوم
این مطلب رو من به تدریج کامل می کنم. روی هر بخش هم شماره می زنم که شما به ترتیب بتونید جلو برید.
پایان قسمت اول
برای دسترسی به بانک اطلاعاتی در وب نیاز به یک ConnectionString داریم که اطلاعات مربوط به سرور بانک اطلاعاتی را در خود نگه داری کند. اگر این کار را برای هر فرم جداگانه انجام دهیم به هنگام publish کردن سایت باید همه فرم ها دوباره ویرایش بشن. اما اگه از Web.Config استفاده کنید لازم نیست همه فرم ها تغییر کنن. فقط Web.Config باید تغییر کنه.
<
configuration><
appSettings/><
connectionStrings><
add name="myConnectionString" connectionString="Data Source=myServerName;Initial Catalog=myDatabaseName;User ID=myUserId" providerName="System.Data.SqlClient"; password="myPassword"/>< FONT>connectionStrings>
برای دسترسی به اطلاعات موجود توی این فایل از کد زیر استفاده می کینم
SqlConnection
cn = new SqlConnection(WebConfigurationManager.ConnectionStrings["myConnectionString"].ToString());