2008年12月26日 星期五

在SQL中使用自訂函數-->十進位轉二進位(12.26)

SQL中要將10進位轉2進位,到底應該怎麼轉呢?
原先想說,
select Convert(binary(10),20),這樣試試
結果,出來的卻是
0x00000000000000000014
天丫,居然變成16進位了,這不是我想要的耶~~
我是希望,打了20,可以幫我轉成「10100」。這樣才對!

在網路上找了挺久,sql似乎沒有這樣的函數,
既然沒有default的,那就自己來寫一個吧!
在c#中,寫function,很簡單,而在sql自訂函數呢?嘻~一樣很簡單
  1. 可程式性」中,有個「函數」,將分支打開後,裡面有sql預設的所有函數,若在找函數用時,可以來參考看看喲!(我也是這次才注意到),直接在「函數」上按右鍵選「新增」,另有一層,是選擇傳回值的資料,看是傳回單值,還是傳回資料表的,這次是要傳回一個轉換後的字串,所以選擇「純量值函數」。
  2. 在新增畫面中,感覺跟「預存程序」差不多嘛~姑且,我將要填入值的地方,分成幾個部份。「說明」「自訂函數名稱」「定義自訂函數參數」「定義回傳資料型態」「宣告回傳值變數」「運算區」「回傳指令」
  3. 確定執行無誤後,接著就是呼叫啦~~~執行: select dbo.ToBinary(20,5)。結果:10100

以下是自訂函數的程式:
-- =============================================
-- Author: 宗
-- Create date: 20081226
-- Description: 將數值資料轉換成二進位字串
-- =============================================

ALTER FUNCTION [dbo].[ToBinary]
(
-- Add the parameters for the function here
@Number int ,--傳入要轉換的數值資料
@Max int --可接受的最大字元數
)
RETURNS nvarchar(31) --共可接受31位數(因為int只到2的31次方)
AS
BEGIN

-- Declare the return variable here
DECLARE @binery nvarchar(31)
set @binery=''
-- Add the T-SQL statements to compute the return value here

--若數值超過所設定的次方數的或是超過函數自訂的31次方,則回傳空字串
if (@Max>31)
begin
return @binery
end

if @Number>power(2,@Max)
begin
return @binery
end
--檢查若都無誤,則進行轉換

declare @min int
set @min =0 --起始值
--進行轉換
while @min<@max+1
  begin
   if @Number=0
    break
   set @binery = Convert(nvarchar(10),@Number % 2)+ @binery;
   set @Number = @Number / 2;
   set @min=@min+1
   end
    -- Return the result of the function
  RETURN @binery
  END  

2008年12月2日 星期二

RadioButton 不准動(12.2)

想要讓CheckBox不能讓使用者點選的話,有很多種方式。
例如:設 Enabled=False,或是來個 disabled,但是呢,這都影響到其外觀,
也就是說,當設了以上的屬性時,他的外觀就會變成是灰色的了。
當然,這樣有好處,也有壞處。這邊就介紹一個可以不影響外觀的小技巧。

<asp:CheckBox ID="CheckBox1" runat="server" onclick="return false;" />

如此一來,怎麼點,他就是不能勾選或取消喲!!

然而,既然 CheckBox 可以用的話,那 RadioButton 應該也可以用吧~~
那就來套套看吧~~
呃~~~結果,動是不能動了,可是,當我是RadioButton群組時,
當點了非預設的選項時,原本預設的選項便會被清空。看來這個小技巧不適合它了。
那就只好寫個小 Function 來協助一下吧!

物件
<asp:RadioButtonList ID="RadioButtonList1" runat="server"  onclick="readonlyRadio(this.id,2)"  >
        <asp:ListItem Value="a">Aasp:ListItem>
        <asp:ListItem Value="b" Selected="true">Basp:ListItem>
        <asp:ListItem Value="c">Casp:ListItem>
asp:RadioButtonList>

JavaScript 函式

function readonlyRadio(name,defaultCheckedIndex) 
{  
    document.getElementsByName(name)[defaultCheckedIndex].checked = true;   
    
}   
看了後,應該是看得懂吧?將預設的選項帶給它,之後,再讓它還原預設的選項就行了!!
對了,有一點要提示的是,有沒有注意到,
這邊使用的是「document.getElementsByName」,而不是「Id」?
原因是,ServerControl RadioButtonList編譯出來的是很多個「input」「type="radio" 」的HTML元件,
其中,將這些input全部以「name」屬性包起來。就跟設Group一樣囉~
所以,當我們在抓時,就該用 getElementsByName 抓呀

2008年11月27日 星期四

何謂「委派(Delegate)?」(11.27)

委派(Delegate):
  1. 委派就如中文表面的意思一樣,就是將我們定義好的方法,透過委派的物件,來執行該方法。
  2. 在我們一般寫程式時,也許甚少會用到委派的東西,但,若你在開發一些共用元件,需要提供方法、事件讓別人使用時,就應該要透過委派來達到安全性及共用性。
範例:

//以下是一個四則運算的簡單範例


    delegate int arithmetic(int num1, int num2); //定義委派類型


    protected void Page_Load(object sender, EventArgs e)
    {
        //先宣告委派
        arithmetic ari=null;

        //設定算術原則
        string fun="/";

        switch (fun)
        {
            //依照fun所給的算術原則,將該算術原則的方法,指派給「ari」
            case "+":
                ari = new arithmetic(this.add);
                break;
            case "-":
                ari = new arithmetic(subtract);
                break;
            case "*":
                ari = new arithmetic(multiply);
                break;
            case "/":
                ari = new arithmetic(divide);//實作委派
                break;
                //(這些方法,必須也要跟定義委派類型的是相同的喲。

就是說,也必須有回傳int,及有兩個數值參數。)
        }

        int ccc = ari(6, 3);//這時候,只要統一用「ari」就可以呼叫對應的方法了。

    }


    private int add(int a,int b)
    {
        //加
        return a + b;
    }

    private int subtract(int a, int b)
    {
        //減
        return a - b;
    }

    private int multiply(int a, int b)
    {
        //乘
        return a * b;
    }

    private int divide(int a, int b)
    {
        //除
        return a / b;
    }



另外,委派也有「組合」的功能,可以將數個方法,一起組合起來,依序執行。
例:
ari += new arithmetic(this.add);
ari += new arithmetic(this. subtract);

如此的話,程式便會先執行「add」完後,接著執行「subtract」。另外,有了「+」,也可有「-」

ari += new arithmetic(this.add);
ari += new arithmetic(this. subtract);
ari -= new arithmetic(this.add);

經過了「-」的動作,原本加上的「add」方法,又被移除了,於是就只會執行「subtract」而已。


2008年11月19日 星期三

按Enter,就執行我要的按鈕(11.19)

常常在網頁中,例如「登入」「查詢」的功能時,
我們會希望輸入完資料後,
按下「Enter」,就能執行登入或查詢的功能,
而不是用滑鼠去點選按鈕,
以往,我們要達到這種目的,
需要用javascript判斷我們所鍵入的按鍵key值
再去觸發該按鈕的事件。

現在,.Net 2.0幫我們包好了我們要的功能囉。

我們可在「Form」標籤裡的「defaultbutton」屬性,
設定我們要執行按鈕的ID即可
又或是可在「Panel」的 ServerControl中的「DefaultButton」也可喲。

使用Panel的話,彈性可以更廣,因為,每個網頁可以有許多個Panel呀
例如,一個網頁中,同時放有登入及查詢的功能,我們就可將其各用Panel包起來
這樣,就可以各自跑各自的DefaultButton了。

用Panel的話,在MasterPage的話,也可通用。



GridView的表頭跨欄設計(11.19)

這個功能,在Google用「GridView 跨欄」去搜尋,就會有一大堆的文章。
對這功能來說,是個老梗了啦!
現下,我便引用某位大大的文章,及配合自己的實例,來幫助註解一下吧。


if (e.Row.RowType == DataControlRowType.Header)
{
TableCellCollection oldCell = e.Row.Cells;
oldCell.Clear();//將原有的表頭格式移除

//產生多重表列的第一列
GridViewRow headRow = new GridViewRow(0,0, DataControlRowType.Header, DataControlRowState.Insert);

//第一欄
TableCell head2Cell = new TableCell();
head2Cell.Text = "單位";
head2Cell.BackColor = row1color();//自訂的方法用以統一取得色彩
head2Cell.HorizontalAlign = HorizontalAlign.Center;
head2Cell.RowSpan = 2;//所跨的欄數
headRow.Cells.Add(head2Cell);//新增自製的儲存格


//第二欄
head2Cell = new TableCell();
head2Cell.Text = "群組";
head2Cell.BackColor = row1color();
head2Cell.ColumnSpan = 8;//所跨的欄數
head2Cell.HorizontalAlign = HorizontalAlign.Center;
headRow.Cells.Add(head2Cell);//新增自製的儲存格

//第三欄
head2Cell = new TableCell();
head2Cell.Text = "聯絡人";
head2Cell.BackColor = row1color();
head2Cell.ColumnSpan = 3;//所跨的欄數
head2Cell.HorizontalAlign = HorizontalAlign.Center;
headRow.Cells.Add(head2Cell);//新增自製的儲存格

//第四欄
head2Cell = new TableCell();
head2Cell.Text = "行事曆";
head2Cell.BackColor = row1color();
head2Cell.ColumnSpan = 3;//所跨的欄數
head2Cell.HorizontalAlign = HorizontalAlign.Center;
headRow.Cells.Add(head2Cell);//新增自製的儲存格

//將自製的資料列新增上去
GridView1.Controls[0].Controls.Add(headRow);

//產生多重表列的第二列
headRow = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Insert);

#region 群組裡的欄位

//用法都與第一列相同
head2Cell = new TableCell();
head2Cell.Text = "使用量";
head2Cell.BackColor = row2color();//自訂的方法用以統一取得色彩
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "成員數";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "員工數";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "通訊錄量";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "檔案總數";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "總檔案量";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "檔案下載次數";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "下載磁碟總量";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

#endregion

#region 聯絡人裡的欄位

head2Cell = new TableCell();
head2Cell.Text = "使用人數";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "聯絡人數量";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "同步次數";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

#endregion

#region 行事曆裡的欄位

head2Cell = new TableCell();
head2Cell.Text = "使用人數";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "events_personal";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

head2Cell = new TableCell();
head2Cell.Text = "events_group";
head2Cell.BackColor = row2color();
headRow.Cells.Add(head2Cell);

#endregion

GridView1.Controls[0].Controls.Add(headRow);


完成後,我們的資料表頭,就會變成下列樣式:


2008年10月21日 星期二

如何在多行的TextBox加入斷行(10.21)

有時候,我們在設計表單要讓使用者填寫時,有時候設定預設的資料格式,如下圖

那我們在程式中,如何設定預設的斷行呢?
Environment.NewLine:取得為這個環境定義的新行字串 (Newline String)。msdn


範例:
txt_content.Text = string.Format(@"時間:{0}地點:{0}主辦單位:{0}執行單位:{0}協辦單位:{0}報名費用:{0}報名方式:{0}聯絡窗口:{0}活動議程:{0}", Environment.NewLine);

2008年10月3日 星期五

IIS 6.0 預設不支援 ASP.NET的程式(10.3)

前幾天,家裡的Server2003系統更新後,IIS也幫我由原本的5版提升到6版了!
結果呢,原本運行正常的程式,後來就都不行了,持續出現如下畫面。







原本以為是IIS壞掉了,於是移除重裝,但,仍然是這樣~~於是上網去搜尋了一下,
果然,已有許多大大遇見過這種問題,也都提供了解法。感謝天~感謝地~感謝這些無私的大大!



簡單地說,就是要新增ASP.NET 2.0的「網頁延伸服務」,並設為「允許」。以下為解法




2008年9月12日 星期五

如何產生辨識圖形(9.12)

現在有很多網頁,它們都會有個圖形驗證的功能。
有時候可能會出現在加入會員,
有時候可能會出現在發表問題、論壇等,
主要就是防止別人使用「程式」來胡作非為,
畢竟,加了一個圖形驗證,是用肉眼來辨識的,
「程式」要突破,就比較難了~~~(或許根本沒法做到)。
那現在,我們來看看這功能是如何達成的。


要產生如此的畫面,建議使用二個網頁,
一個是主畫面,另一個是負責畫圖的。
以下採用
「Default.aspx」:主畫面
「Default2.aspx」:畫圖的網頁
來制作

程式碼 Default.aspx.cs


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.Drawing;//畫圖相關的類別


public partial class _Default : System.Web.UI.Page
{

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{

//產生圖形

BindIMG();

}

}

#region 產生圖形

private void BindIMG()
{

//定義圖形大小、圖形解析度
Bitmap BMP = new Bitmap(300, 100,System.Drawing.Imaging.PixelFormat.Format24bppRgb );

Graphics formGraphics = Graphics.FromImage(BMP);

//內填滿

formGraphics.FillRectangle(new SolidBrush(Color.PaleGoldenrod
), 0, 0, 300, 100);

string drawString = "";

//用亂數取六位數

Random rnd = new Random();

for (int i = 0; i < 6; i++)
{

drawString += string.Format("{0} ", rnd.Next(9));//產生小於10的整數

}



//定義字型,大小

Font drawFont = new Font("Comic Sans MS", 32);

//定義筆刷顏色

SolidBrush drawBrush = new SolidBrush(Color.YellowGreen
);

//座標位置

Single x = 20;
Single y = 15;

//畫出內容

formGraphics.DrawString(drawString, drawFont, drawBrush, x, y);

//釋出資源
drawFont.Dispose();
drawBrush.Dispose();
formGraphics.Dispose();


//將繪圖相關存到session,在另一個網頁拿來用


Session["BMP"] = BMP;

//由另一個網頁輸出

Image1.ImageUrl = "Default2.aspx";


}
#endregion

}



程式碼 Default2.aspx.cs


using System;
using System.Data;
using System.Configuration;
using System.Collections;
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.Drawing;
using System.IO;


public partial class Default2 : System.Web.UI.Page
{

protected void Page_Load(object sender, EventArgs e)
{
//利用剛剛存到session的圖片讀出
Bitmap BMP = (Bitmap)Session["BMP"];
MemoryStream tempStream = new
MemoryStream();
//將圖片存到記憶體
BMP.Save(tempStream,System.Drawing.Imaging.ImageFormat.Png);

Response.ClearContent();
Response.ContentType = "image/png";
Response.BinaryWrite(tempStream.ToArray());//將圖片用二進位輸出
Response.End();

}

}



由於圖片是根據我們製作的「drawString」字串畫出來的,
接下來若要判斷的話,我們則使用它來比對使用者輸入的文字即可。

2008年8月23日 星期六

出現「這個安裝不支援這種專案類型」?(8.23)

由於要承接別人案子的緣故
所以我的同夥將他的程式整包丟給我
那想當然爾,就一如往常的要將專案建置起來
沒想到,出乎意料的搞不定
出現了這樣的錯誤訊息,讓我苦惱一時
後來又看到這個專案裡的程式
跟我們一般的不同,就是一支網頁不只有
*.aspx
*.aspx.cs
又多了
*.aspx.designer.cs
這樣的東西
這一下這支程式裡的內容,似乎只是介紹控制項而已。
後來上網查了一下
原來是因為此專案在設計時
已經安裝了VS2005 SP1 的 Service Pack
所在這個專案在新增時,就會另外出現這樣的程式(*.aspx.designer.cs
而原本尚未安裝SP1的我,遇到這種不認識的程式
就會發生錯誤,專案自然就開啟不了
所以,記得請先安裝VS2005 SP1 再開專案吧。

2008年8月7日 星期四

物件導向程式設計_介面(Interface)(8.6)

何謂介面(Interface):
在google上,的確有著非常多相關於介面(Interface)的討論、說明。
不曉得是不是本人智商過低,亦或是人家講的不清楚? 我是都有看沒有懂。
不過,看大家在都可以在各論壇討論得沸沸騰騰,所以,猜想答案應該是前者吧(本人智商過低)。
但是,畢竟用一種說法,並不代表可以說懂每一個人嘛,不然,哪來的「因材施教」呢?
也幸好,本人並非「朽木不可雕也」,看了一堆人的說法,總算是有點心得。
其實,透過字面上,我們也可以看得出來「介面(Interface)」是什麼東西。
就是某個東西,要操控、使用另一個東西時,中間的橋梁,
就像我們在使用電腦時,會有一個介面(window畫面),來指引你使用,
我們在看電視轉台時,會有個搖控器或是選台的按鈕讓你來轉台。
這邊主要的觀念是想說,「介面(Interface)」主要就是構成二者互動的橋梁。
有了這個概念後,我們把概念帶到程式這邊來:
介面(Interface)就是「程式碼」與「類別(Class)」之間的橋梁。
當然,我們在寫程式時,也不見得會採取介面(Interface)的方法,
我們會直接「程式碼--->類別」,並不會「程式碼--->介面--->類別」的流程。
只是說,若使用介面(Interface)的話,它們的關係,是這樣子的。
介面(Interface)的使用:(C#)
interface IHardDisk
{
void setDefault(); //設定硬碟容量的起始值
bool compareHD(int HD); //比較看哪個容量大
int HD_gigabyte{ set;get;} //設定/取得硬碟容量
public void errtest();
}
小提醒:
  1. 一般習慣,在命名介面(Interface)時,都以「I」為開頭表示Interface。
  2. 在定義介面(Interface)時,裡面的方法,屬性都只「定義」而已,並未真正的實作內容
  3. 由於,此為測試,所以真正在應用時,請適時地加上「Public」修飾詞。ex: Public interface IHardDisk {...}。
  4. 上面紅色字體,表示為錯誤的使用方法:不用加上「Public」修飾詞.
看完了如何定義一個介面(Interface)後,我們接著看範例。
介面(Interface)範例:
範例說明(實作):
  1. 定義介面(IHardDisk)
  2. 利用類別(HardDisk)實作介面
  3. 程式中,一改以往呼叫類別的方法,改以呼叫介面
  4. 使用該介面的各屬性、方法
小提醒:
  1. 在實作介面時,該介面所定義的方法、屬性,在類別那,都要一一實作
  2. 在實作介面時,每個「方法」都請加上修飾詞「Public
  3. 程式宣告時「IHardDisk ComputerHD=new HardDisk() ; 」,後面是 new 一個類別。
程式碼:
---------------------------------------------
interface IHardDisk
{
void setDefault(); //設定硬碟容量的起始值
bool compareHD(int HD); //比較看哪個容量大
int HD_gigabyte{ set;get;} //設定/取得硬碟容量

}
class HardDisk : IHardDisk //實作IHardDisk的介面
{
//將介面的各個方法、屬性實作出來
int hd_gigabyte;//宣告一個變數來存取硬碟容量的值

public void setDefault()//實作「設定起始值」的方法
{
hd_gigabyte = 520;
}

public bool compareHD(int HD)//實作「比較大小」的方法
{
if (HD > hd_gigabyte){return true;}
else{return false;}
}

public int HD_gigabyte //實作「取得/設定容量」的屬性
{
get { return hd_gigabyte; }
set {hd_gigabyte=value;}
}
}

protected void Page_Load(object sender, EventArgs e)
{
IHardDisk ComputerHD=new HardDisk() ; //宣告
ComputerHD.setDefault(); //設定硬碟容量的預設值
Response.Write(ComputerHD.HD_gigabyte); //取得硬碟容量
Response.Write(ComputerHD.compareHD(567)); //比較大小

}
--------------------------------------------
為何要使用介面(Interface):
看了以上的範例,會有個想法:這種作法,比我直接呼叫類別的方法還要繁瑣
我直接將方法寫在類別裡,再呼叫類別使用就好啦!(「程式碼--->類別」)
何必要這麼麻煩,還透過介面,多了一道手續(「程式碼--->介面--->類別」)
沒錯,藉由以上的範例,的確看不出用介面(Interface)的好處。
然而,使用介面的好處在於「泛用」。
所謂的「泛用」或許可以解釋成「廣泛地使用」,
也就是說,我們只要使用介面,就可以使用不同的類別(前提為,該類別必須實作該介面)
範例說明:(實作)
  1. 相同地我們定義一個介面(Interface)
  2. 另外,我們產生兩個類別一個適用於小型硬碟(miniHardDisk),另一個適用於大型硬碟(bigHardDisk)
  3. 兩者也都實作了IHardDisk的介面
  4. 再來,我們又新增了一個類別,這個類別裡,定義的方法為回傳一個介面的型態(將來都實作產生這個類別)
  5. 在程式碼中,可看到,我們在Computer的類別裡,我們目前是使用「小型硬碟」
  6. 在Page_Load中,我們輸出了介面,及二類別的資料
程式重點:
  1. 程式中,我們目前是使用「小型硬碟」,若突然要改成「大型硬碟」時,我們只需更動,Computer的類別即可,程式碼,完全不用更動
  2. 將類別中的「miniHardDisk cc = new miniHardDisk();」,改成「bigHardDisk cc = new bigHardDisk ();」
程式碼:
======================================

interface IHardDisk
{
void setDefault();//設定硬碟容量的起始值
bool compareHD(int HD);//比較看哪個容量大
int HD_gigabyte { set;get;}//設定/取得硬碟容量

}

class miniHardDisk : IHardDisk //實作IHardDisk的介面
{
//將介面的各個方法、屬性實作出來

int hd_gigabyte=0;//宣告一個變數來存取硬碟容量的值
public void setDefault()
{
hd_gigabyte = 40;

}
public bool compareHD(int HD)
{
if (HD > hd_gigabyte){return true;}
else{return false;}
}
public int HD_gigabyte
{
get { return hd_gigabyte; }
set {hd_gigabyte=value;}

}
}
class bigHardDisk : IHardDisk //實作IHardDisk的介面
{
//將介面的各個方法、屬性實作出來

int hd_gigabyte=0;//宣告一個變數來存取硬碟容量的值
public void setDefault()
{
hd_gigabyte = 1024;

}
public bool compareHD(int HD)
{
if (HD > hd_gigabyte) { return true; }
else { return false; }
}
public int HD_gigabyte
{
get { return hd_gigabyte; }
set { hd_gigabyte = value; }

}
}

class Computer
{
public IHardDisk Disk()
{
miniHardDisk cc = new miniHardDisk();
cc.setDefault();
return cc;
}
}


protected void Page_Load(object sender, EventArgs e)
{

IHardDisk Iabc = new Computer().Disk();
Response.Write("使用介面取得的值:");
Response.Write(Iabc.HD_gigabyte);
Response.Write("<br><br>");

Response.Write("使用bigHardDisk類別取得的值:");
bigHardDisk bHD = new bigHardDisk();
bHD.setDefault();
Response.Write(bHD.HD_gigabyte);
Response.Write("<br><br>");

Response.Write("使用miniHardDisk類別取得的值:");
miniHardDisk mHD = new miniHardDisk();
mHD.setDefault();
Response.Write(mHD.HD_gigabyte);



}

======================================
議題:
這時,也會有個疑問:
既然這樣的話,我還是一樣可以使用類別呀,
反正也是一定要創造兩個類別,那我在Page_Load時,再改呀
類別的寫法-->
Response.Write("使用bigHardDisk類別取得的值:");
miniHardDisk mHD = new miniHardDisk ();
mHD .setDefault();
Response.Write(mHD .HD_gigabyte);
Response.Write("<br><br>");
那當我要由小型硬碟改成大型時,就把
miniHardDisk mHD = new miniHardDisk ();
改成
bigHardDisk bHD = new bigHardDisk();
也行呀。
------------>
很好,說得沒錯,不過,首先,會先遇到個問題
「命名」,已由 mHD --> bHD ,勢必程式碼裡面的名稱都要修改
再者,假設,不修改名稱,我就硬用 mHD 用到底,反正都可以用嘛。
是啊,可以用,可是,又面臨到另個問題,
目前程式是只有一頁而已,那假設,我們已經使用原先物件的寫法,寫了10頁,
甚至於好幾十頁,請問,你要一支一支改嗎?
那如果我們使用「介面」的方法,就只要修改我們類別庫裡的該Computer類別即可。

2008年7月11日 星期五

2008年6月18日 星期三

Silverlight初探(6.17)

Silverlight 是微軟針對下一代Web所推出的新技術,本身具備了「向量動畫」、「2D繪圖」、「影音播放」,達到更好的視覺化效果與互動性。

架構特點

  1. 輕量級的瀏覽器plug-in:安裝元件的大小只有1.4MB。
  2. XAML為基礎,能夠產生向量文字、2D繪圖、影音播放。
  3. 與既有技術的整合:可與既有的HTML、DOM、CSS、AJAX技術搭配運用。

跨平台與跨瀏覽器能力

詳細對應表:資料來源

OS/瀏覽器

IE 7

IE 6

Firefox 1.5

Firefox 2

Safari

Windows Vista

Yes

-

Yes

Yes

-

Windows XP

Yes

Yes

Yes

Yes

-

Windwos 2000

-

Yes**

No

No

-

Windos Server 2003

Yes

Yes

Yes

Yes

-

Mac OS (PowerPC)

-

-

Yes*

Yes*

Yes*

Mac OS (Intelbased)

-

-

Yes

Yes

Yes

附註:上表中「*」表示只支援「Silverlight 1.0 」;「**」表示只支援「Silverlight 2」。資料日期:2008/6/17

問:有否支援「Linux」?

答:目前微軟官方並無打算推出Linux版的安裝程式,但民間已經人開始製作支援的程式。

開發環境

  1. 開發Silverlight 程式最基本只需安裝Silverlight Runtime Component軟體,隨後用記事本(Notepad)開發。
  2. 若希望在VS2005開發,請先安裝VS 2005 SP1 修補後,再安裝 Silverlight 1.0 SDK 。透過工具,產生 Silverlight 專案樣板。
  3. 而在ASP.NET AJAX 專案中,只需將 Silverlight 的 Silverlight.js 及相關的 JavaScript 檔引用即可。
  4. 如欲在VS2008開發,請下載安裝Silverlight Tools ,及Silverlight 2 SDK ,即可開啟樣板使用。
  5. 使用Microsoft® Expression Blend 開發,以所視即所得之圖形化界面。官方網頁(微軟)

最佳應用場景

  1. 網頁媒體領域,如:商業影片、動畫廣告…等。
  2. 網頁小程式,如:網頁遊戲…等。
  3. 網頁視覺化資料與圖形分析,如:財務圖形、地圖…等。

參考範例

  1. 線上鋼琴
  2. 華航精緻旅遊
  3. 微軟Silverlight

開發示範

1.建立新專案「Silverlight」(VS2005)
2.可以看到,程式自動幫你產生好了相關的檔案
3.程式也自動幫你做好了個簡單的按鈕範例
4.另外,可以發現,Silverlight的網頁按了右鍵後,是會顯示組態的檔案(相關資訊)

2008年6月14日 星期六

不使用 SqlDataSource 的 GridView 排序(6.14)

排序是個很簡單的東西嘛 ~ 常常在使用 GridView 的人都知道,
不就是把「AllowSorting」的屬性設成「True」,
以及將對應的欄位「SortExpression」屬性,設為該欄位名稱

沒錯!若是使用 SqlDataSource 的話,的確這樣就可以輕易達到排序的功能。
但,如果您的資料來源(DataSource),不是指定「DataSourceID ="某SqlDataSource 控制項"」
而是使用資料表(DataTable、DataView)來當資料來源的話

若單純如此設定,可是會踢到鐵板的喲~~




必須還要另外引發一個事件 Sorting



程式碼檢視

2008年6月12日 星期四

快速的檢查所有的欄位 (6.12)

不知各位有否曾經何時寫過類似如此的判斷句:


if ( TextBox1.Text != "" && TextBox2.Text != "" && ...)

我想,這是一般在檢查必填欄位時,會用到的判斷語句吧~


我們來假設一下,
若現在這個網頁有30個 TextBox 的控制項,且,希望全部都是必填欄位
又或是,由於目前 SQL Injection 與 XSS 的盛行,想要對每個欄位進行檢查過濾字元
如果是採用原先的寫法,這樣,可能會寫的很累。


或許,您可改寫成這種方式會讓您省事許多:



可利用「Panel」將全部的元件包起來,並以迴圈的方式檢查 Panel 裡所有的TextBox

當 .Net AJAX 遇上 Frame (6.12)

適用了 .Net 包裝的 AJAX 一些時間後,發現,真的是「水能載舟,亦能覆舟」。

在使用前,只知道 AJAX 的優點,衝著它的優點去使用它,
卻沒想到,它也是個會另人頭痛的東西呀~~


目前有個專案,由於必須即時更新資料,所以,想到用使用 AJAX 套件的 UpdatePanel ,
讓它局部更新就好,畫面就不會一直閃。有了這個前題,開始著手製作這簡單的功能。


沒錯,它的確很簡單,所以三兩下就可以完成,且也在本機測試正常,可以即時更新資料;
但是,當我把它放上「測試區環境」時,居然發現,只要滑鼠點了一下(不管左鍵,右鍵),
馬上跳出個 「JavaScript」的錯誤,錯誤上顯示著「存取失敗」

天吶 ~ 發生了什麼事,且是莫名奇妙的發生,對我這 AJAX 的初學者來說,可是個大問題。
明明在本機端不是正常嗎?怎麼到了測試區就壞了?

既然本機正常,測試區故障,那就即有可能是環境的問題。立即檢視了一下環境,
並且馬上再上 Google 尋找問題點,及解決方案,後來,總算是發現問題了。

看來這問題,並不是只有出現在我身上,已有許多前輩遇到,並也提出了解決方案。
真的太好了!現在,就來看看發生了什麼問題吧~

原來問題是出在「Frame」呀~若只是一般的框架,就還沒事,但若是遇到框架內,
左右(或是上下什麼的)網頁的來源路徑處於不同的主機時,
很抱歉,JavaScript 會出來跟您 聊個天,告訴您「存取失敗」。


那這是什麼原因呢?為什麼不同主機時,就會壞掉。經過網路前輩的分享,
得知原來問題就出在 .Net AJAX 的套件中,有個 MicrosoftAjax.debug.js 檔案,

裡面有部份語法是這樣寫的:

var offsetL = w.screenLeft - top.screenLeft - top.document.documentElement.scrollLeft + 2 ;

如果 Frame 的網頁路徑在不同主機上,使用了「top」當然會有問題(算是Bug吧),
但由於,這些程式,已經由 .Net 包起來了,無法直接去修改,
所以,我們便必須另外下載「Microsoft AJAX Library 」來用。

解壓縮後,將其,放在您的「虛擬目錄」底下,接著,
修改一下 ScriptManager 的內容:





再來,修改程式「MicrosoftAjax.debug.js 」中


case Sys.Browser.InternetExplorer: 到 case Sys.Browser.Safari:


修改成:





之後呢? ScriptManager 就會依照您給的路徑去執行該修改過的檔案。


參考來源:黑暗執行緒

2008年5月22日 星期四

Visual Studio 2008 發表會(訊光科技主辦)

微軟在今年發表了「Visual Studio 2008」的產品,此產品,當然比早前的「Visual Studio 2005」的功能多了許多。現在,我們來看看是如何呢??

.NET Framework3.5


  • 在新版的 VS 中,主要是採用了最新的 .NET 3.5的技術
  • 主要的核心程式還是以 2.0為基礎
  • 所以向下相容到 .NET 2.0
  • 「2.0」->「3.0」->「3.5」是以功能的方式新增,核心程式相同。

多版本支援

  • 在建立專案、開啟專案時,都可決定使用的 .NET 版本( 2.0、3.0、3.5)
  • 視專案為何種.NET版本,而會顯示何種功能(三種版本的功能不同)
  • 由於核心程式相同,所以升級也變得相當簡便
  • 針對 JavaScript 有偵錯功能

LINQ

  • 將資料的查詢、設定與轉換的作業,融合於 .NET 程式中
  • 它會根據我們想查找的資料類型(MS SQL、陣列、 DataSet、等)轉換成該種語法
  • 至少支援「LINQ to Objects」「LINQ to DataSets」「LINQ to SQL」「LINQ to Entities」「LINQ to XML」
  • 網路上,已有不少人開始自行撰寫「LINQ to Oracle」
  • 所以只有學會「LINQ」語言,則可以在 .Net 的世界裡,查詢各種資料庫的資料

Silverlight

  • 跨平台(Windows、Mac、Linux)
  • 跨瀏覽器(IE6-8、Firefox、Safari 3.x)
  • 多技術(.NET、AJAX)
  • AJAX的執行效能上,會比JavaScript快一仟多倍。
  • 只能用「屌」來形容
  • 範例網站:華航精緻旅遊(需先安裝Silverlight 1.0)
  • 另一個範例網站是「故宮博物館」的「清明上河圖-清院本」(超屌)
  • 可惜故宮的目前還在發表階段,未完成。沒有放在官網上。

程式碼分析 Code Analysis

  • 提早在開發初期發現問題
  • 如同 .NET 專家幫你檢視程式碼的優劣
  • 超過 230種檢查規則

程式碼指標 Code Metrics

  • 提供程式碼的健康指標
  • 為每段程式碼進行分析,給予「評分」及「紅綠黃」燈顯示
  • 依據「類別耦合度」「繼承深度」「程式碼行數」「程式碼深度」「維設度指數」

執行效能分析

  • 軟體自動操作(執行就會幫你分析了)
  • 找出花最多時間的地方
  • 比較兩次測試的結果

新的壓力測試

  • 可以模擬上百萬人執行開發的網頁、確定網頁執行正常否

2008年5月21日 星期三

AJAX 初探 (Part 1)(5.21)

書刊:Learning ASP.NET 2.0 with AJAX



AJAX所包含的技術:


  • 畫面部份:XHTML、CSS、DOM

  • 資料處理部份:XML、XSLT

  • 資料前後端的傳送:XMLHttpRequest


ScriptManager



  • 使用 VS 2005 需再另外下載「ASPAJAXExtSetup.exe」。

  • 微軟用來整合各種技術來達成 AJAX 技術的元件

  • UpdatePanel 搭配使用

  • 下載網頁:http://www.asp.net/ajax/downloads/

AjaxControlToolkit



  • 使用 VS 2005 需再另外下載「AjaxControlToolkit」。

  • 將下載的範例裡「AjaxControlToolkit\SampleWebSite\Bin」裡的「dll」檔,複製至想要的地方。

  • 在工具箱中加入「新索引標籤」,並加入「AjaxcontrolToolkit.dll」即可載入39個 Toolkit工具。

  • 下載網頁:http://www.asp.net/ajax/downloads/

  • 嵌入Ajax control Toolkit工具箱教學



2008年4月24日 星期四

Threading (Part 4)(4.24)

書刊:Application Development Foundation


其它同步的方法(p.398)
  • ReaderWriterLock
  • Mutex
  • Sempaphore
  • AutoResetEvent
  • ManualResetEvent

ReaderWriterLock(p.398)

  • 定義鎖定:單一寫入器和多重讀取器
  • 不像其它同步的方法,它可以容許同時多個執行緒進行讀取
  • 如果資源不常變更的話,此方式的效能會比 Monitor 佳
  • 使用 AcquireReaderLock 來取得讀取鎖定
  • 使用 AcquireWriterLock 來取得寫入鎖定
  • 使用 ReleaseReaderLock/ReleaseWriterLock 來解除鎖定
  • 使用 UpgradeToWriterLock 來由讀取升級為寫入鎖定
  • 使用 DowngradFromWriterLock 來由寫入還原為讀取鎖定

Mutex(p.402)

  • 和 Monitor 類似
  • 具有跨 AppDomain 的功能

Semaphore(p.405)

  • 具有跨 AppDomain 的功能
  • 可以自行限制允許的緒行緒數量(一般只能一個)

Event(p.406)

  • 具有跨 AppDomain 的功能
  • 分為「AutoResetEvent」及「ManualResetEvent」

2008年4月17日 星期四

Threading (Part 3)(4.17)

書刊:Application Development Foundation



Lession 2 : 共享資料的存取(Sharing Data)(p.387)


防止資料衝突(Avoiding Collisions)


  • 在多個執行緒同時共用同個全域變數執行時,會發生重覆存取的狀況

生活範例 :

假設在Server上有個 Word 檔,希望3個人(A,B,C)在上面簽名,

命令一發出去,3個人跑來要簽名,A 很快的取得頭籌搶先簽到名,

所以在該檔上,有了 A 的簽名,再來 B 也很快的把 Word 檔讀出去要簽名,

此時,C 也把檔案讀了出去,當 B 簽好名,把 Word 檔存了進去,

進而,C 也簽好了,把他的 Word 檔存了進去。

這時候發生了個狀況,發現,上面居然沒有 B 的簽名。

因為,B 簽名的那個檔案,被 C 的檔案蓋掉了。

這就是該本課的重點,教導如何將這些全域的資料鎖定(只有單一執行緒能讀取)



單一數值變數適用(p.390) :

  • Interlocked Static Methods
  • Add : 將兩個64位元的整數相加,並以總合取代第一個整數
  • Decrement :遞減特定變數並將其儲存
  • Exchange : 將平台特定的控制代碼或指標設定為指定值,然後傳回
  • Increment : 遞增特定變數並將其儲存
  • Read :傳回64位字的值
  • 以上皆為「不可部份完成」(鎖定)
  • 效能比較好(如果只做遞增減運算)

程式範例



區域型適用 :

  • lock(簡單型)(p.394)
  • Monitor Static Methods(進階型)(p.395)
  • Enter :取得指定物件的獨佔鎖定
  • Exit :釋出指定物件的獨佔鎖定
  • TryEnter :嘗試取得指定物件的獨佔鎖定(在指定時間內)
  • Wait :釋出物件的鎖定,並且封鎖執行緒,直到此執行緒重新取得鎖定

程式範例


Understanding Deadlocks(p.396)

  • 由於要執行的程式,被鎖定,而使程式在那
  • 可利用 Monitor.TryEnter 方法,並設定鎖定時間來解決


程式範例


2008年4月10日 星期四

Threading (Part 2)(4.10)

書刊:Application Development Foundation




















帶參數的執行緒(Passing Data to Threads)(p.377)
  • 必須使用 ParameterizedThreadStart 的物件來委派
  • 指定委派的方法,必須是個有帶 object 型態參數的方法
終止執行緒(Stopping Threads)(p.379)
  • 使用 theThread.Abort() 來執行終止執行緒( theThread 是物件名稱)
  • 適情況來使用「關鍵區域(CriticalRegion)」,防止執行緒執行不完全
  • Thread.BeginCriticalRegion() => 關鍵區域起點
  • Thread.EndCriticalRegion() => 關鍵區域終點
  • 當執行緒處於關鍵區域時,它會繼續執行直到離開關鍵區域才終止(Stop)
執行背景內容(Execution Context)(p.381)
  • 每個執行緒都有散播相關資訊給下一代的能力
  • 相反地,每個執行緒都會繼承其相關資訊
  • 優點:直接可接收相關資訊來使用
  • 缺點:繼承的過程中比較耗效能
  • ExecutionContext 類別提供「SuppressFlow」、「RestorFlow」來控制是否繼承
  • 透過 AsyncFlowControl 來移轉資料流達到關閉的效果
  • 利用 theFlow.Undo() 重新開啟散播功能( theFlow 是 AsyncFlowControl 物件名」
  • 若要在關閉散播功能後,繼續使用相關資訊,可在「前面」加入 ExecutionContext.Capture()來備份一份,之後要使用時,再利用 ExecutionContext.Run 來執行指定的內容
相關的使用方法,請參見「程式範例」


程式範例


2008年4月8日 星期二

TreeView 的 CheckBox (4.8)

在使用 TreeView 的時候,很簡單地,大家都知道,
只要將其「ShowCheckBox」的屬性設為「True」,在該節點上,
就會產生「CheckBox」型的節點。

另外發現它也有個「TreeNodeCheckChanged」的事件,
其事件的意義就是一如往常的,只要有「勾選/取消」的動作,就會觸發。
很好,那我們便很自然地去找「AutoPostBack」的屬性…

啊?居然沒有~~那也許是程式自己已經是預設「AutoPostBack=True」了吧。
於是執行程式,可是…
它居然沒有執行「TreeNodeCheckChanged」事件底下的程式???

原來,這就是很多人指出 TreeView 的 CheckBox 半殘的地方。
因為還要另外自己再加入些程式碼(JavaScript)才行。

//要加入這個,才能引發TreeView的OnTreeNodeCheckChanged事件
function doCheck()
{
//設定「o」為產生click的來源元素(物件)
var o = window.event.srcElement;

//下條件判斷:屬於checkbox的物件,才產生postback
if (o.tagName == "INPUT" && o.type == "checkbox")
{
__doPostBack("","");
}
}

並把該「TreeView」物件,加一個「onclick="doCheck()"」的事件。

2008年4月3日 星期四

Threading (part 1)(4.2)

書刊:Application Development Foundation

何謂「Threading」?(p.367)


  • 「Threading」為開發軟體裡中,甚為重要的一個觀念,主要就是能使程式正確地同時執行數個運算。也就是大家所稱的「多工」。

本章的內容,將分成三個課程。

  • Lesson 1 : Creating Threads
  • Lesson 2 : Sharing Data
  • Lesson 3 : The Asynchronous Programming Model

測試練習的方法(p.368) :

  1. 新增一個「主控台應用程式(Console application)」
  2. 在前面的部份加入參考「Using System.Threading」(C#)
Lession 1 : 產生執行緒(Creading Threads)(p.369)


介紹執行緒(Threads)

  • 執行緒重要屬性(Threads Properties) (p.369)
  • IsAlive : 指出目前的執行狀態
  • IsBackground : 是否背景執行
  • IsThreadPoolThread : 是否屬於Managed執行結果
  • ManagedThreadId : 唯一識別項
  • Name : 執行緒名稱
  • Priority : 指定或取得優先權
  • ThreadState : 目前執行緒的狀態
  • 執行緒方法(Threads Methods)(p.370)
  • Abort : 結束執行緒(無法再用Start啟動)
  • Interrupt : 插斷在WaitJoinSleep的執行
  • Join : 封鎖呼叫執行緒
  • Resume : 恢復執行緒
  • Start : 把目前的執行個體改成以thread執行(啟動執行緒)
  • Supend : 將執行緒暫停
  • 執行緒靜態屬性(Static Thread Properties)(p.370)
  • CurrentContext : 取得執行緒正在執行的內容
  • CurrentPrincipal : 角色架構安全性用
  • CurrentThread : 取得目前執行的執行緒
  • 執行緒靜態方法(Static Thread Methods)(p.371)
  • BeginCriticalRegion
  • EndCriticalRegion
  • GetDomain
  • GetDomainID
  • ResetAbort
  • Sleep : 封鎖目執行緒一段指定的時間
  • SpinWait
  • VolatileRead
  • VolatileWrite
  • 執行緒狀態列舉(ThreadState Enumeration)(p.371)
  • Aborted : 結束狀態
  • AbortRequested : 被要求結束中
  • Background : 背景執行
  • Running : 已啟動
  • Stopped : 已停止
  • StopRequested : 被要停止中
  • Suspended : 已經暫停
  • SuspendedRequested : 被要求暫停中
  • Unstarted : 未被呼叫啟用
  • WaitSleepJoin : 因為呼叫「Momtor.Wait」「Thread.Sleep」「Thread.Join」而被封鎖
  • 執行緒的優先權列舉(Thread Priority)(由最高到最低)(p.376)
  • Highest
  • AboveNormal
  • Normal
  • BelowNormal
  • Lowest


程式範例 (主要介紹「委派產生執行緒、啟動Start()、延緩Sleep()、封鎖Join()」)


2008年3月26日 星期三

Events and Code (3.27)

書刊:Beginning.ASP.NET.2.0(Wrox)


Web Server 架構(p.181)

  1. Post:將資料包裝在Http標頭內傳送給WebServer
  2. Get:把資料直接加在URL之後傳送

使用Server Controls可以克服Http的「Statelss(無記錄狀態)」的特性(p.182)

  • 一般的Html Controls在執行Sumit(Post)動作時,網頁元件會回復成原來未輸入資料的樣子,但Server Controls有著「PostBack」的功能,可以將元件資料Sumit給自己,所以便可保留狀態

PostBack 架構(p.190)

  1. PostBack顧名思議就是「post」->「back」,將網頁資料先post給自己後(記錄狀態)再傳送到WebServer
  2. 另外由於 PostBack的緣故,網頁在執行時每次都重跑一次「Page_Load」,所以可以另外加「IsPostBack」判斷是否「PostBack」來執行指令

事件觸發時機((p.195)

  1. 使用者控制(ex. Click)
  2. 繫結資料庫時(ex. DataBound、ItemDataBound)
  3. ASP.NET引發(ex.DataBind)(使用者另外要求)

取消事件(Canceling Events)(p.203)

  • 在對資料庫進行異動時(Inserting、Updating等...),另外可以有「取消」的事件,進行取消的動作。指令: e.Cancel(2.0新功能)

Global事件(Global Events)(p.206)

  1. Application_Start:在Web伺服器(IIS)啟動時,並且有第一個使用者執行程式時觸發
  2. Application_End:Web伺服器(IIS)關閉或停止時觸發
  3. Session_Start:網頁開始執行時(開始存取網頁)時觸發
  4. Session_End:Session TimeOut時觸發
  5. Application_Error:程式執行期間的例外狀況,如果沒有用「try...catch」攔的話,都會跑到此事件
  6. Profile_OnMigrateAnonymous:當設定檔的匿名使用者登入時觸發(2.0新功能)


取得網頁的HTML原始碼(3.26)

圖一
圖二
圖三


案例:
在Google Patents搜尋(圖一)中,鍵入:「Patent:XXXXXX」,可以取得與此相關的專利(列表)(圖二)。
但目前有個需求是希望在自己的網頁中,建立一個UserControl,來取代「Google Patents」(圖一)的畫面
此UserControl裡放置了「TextBox」、「Button」各一個,希望能在使用者輸入「專利號」
就可以馬上連結到該專利的網頁(圖三),而非「一個列表(圖二)」。


問題來了,要連到專利的網頁(圖三),必須要知道該專利的id(由google的url得知)
但是,id是存在google他們的資料庫呀,我們如何知道呢?


其實,在列表中的超連結,已有專利的id可見,所以只要利用「WebRequest
攔截列表的html,再找出該專利的id,這樣就可以自己串連到專利網頁的URL了。




// 設定request
System.Net.WebRequest request = System.Net.WebRequest.Create(pageUrl);
//設定TimeOut的時間(怕網路速度過慢,資料不完全)
request.Timeout = timeoutSeconds * 1000;

// 從request接收資料
System.Net.WebResponse response =request.GetResponse();
System.IO.Stream streamReceive = response.GetResponseStream(); System.Text.Encoding encoding = System.Text.Encoding.GetEncoding("utf-8"); System.IO.StreamReader streamRead = new System.IO.StreamReader(streamReceive, System.Text.Encoding.Default);

// 取得原始碼
String HTML =streamRead.ReadToEnd();

2008年3月7日 星期五

SQL Server中利用「Cursor」取得每一筆資料

左方資料表,如何將其資料一筆一筆的讀取出來進行運算呢?可以使用「Cursor」來達到我們所要的要求!!
*右圖為依序取出資料的結果~

以下為簡單的應用

語法:

declare @no nchar(2)
declare @name nchar(10)
-----宣告讀取資料的cursor------
declare city_cursor
CURSOR for
SELECT City_no,City_name from dbo.City

open city_cursor --開啟COLUMN_cursor

fetch next from city_cursor into @no,@name --把取出來的值存入變數
while @@FETCH_STATUS = 0
--判斷city_cursor是否還有資料
begin
print '編號:'+ @no
print '地區:'+@name
fetch next from city_cursor into @no,@name--進行下一筆
end
close city_cursor --關閉city_cursor
DEALLOCATE city_cursor --移除city_cursor