2009年12月14日 星期一

保存DataTable

在window form的程式中,DataSet或DataTable的存續在window form程式設計師眼裡視之理所當然,但是在web form就不是這般,因為web的本質在使用者發出要求(Request),web server依據要求處理後再回應(Response)給使用者,二者之間的關係在工作結束後就中斷了,這些 In memory物件(DataSet、DataTable)就會消失,如果要保留DataSet、DataTable可以利用Session或ViewState來保留,下面介紹利用ViewState使DataTable得以存續

protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if (ViewState["_dt"] != null)
{
dt = (DataTable)ViewState["_dt"];
}
}

protected override object SaveViewState()
{
ViewState["_dt"] = dt;
return base.SaveViewState();
}

上面的程式片段將利用DataTable存入ViewState及ViewState明確轉型為DataTable,令DataTable得以存續,不過在使用時至少要考慮一些問題
1)系統頻寛
2)系統Loading
因為是存在ViewState所以對於使用者與Server往來的流量就會增加,另外使用者的瀏覽器在解析時也會較慢,還有在ViewState轉型成DataTable也會耗用資源,以上都是在使用時要考量的。

2009年12月10日 星期四

ADO.NET-DataRowState說明

每一個DataRow物件的狀態可能為以下五種其中一種

1)Added
2)Deleted
3)Detached
4)Modified
5)Unchanged

其中Added、Deleted、Modified會對資料來源產生異動。
Added: 對應SqlDataAdapter的InsertCommand
Deleted: 對應SqlDataAdapter的DeleteCommand
Modified: 對應SqlDataAdapter的UpdateCommand

Added狀態 是DataRow加入至DataTable,尚未呼叫AcceptChanges
Deleted狀態 是DataRow利用Delete方法刪除資料列
Modified狀態 是DataRow修改,尚未呼叫AcceptChanges

當SqlDataAdapter物件呼叫Update方法時就是利用DataTable中每一筆DataRow的狀態去對應適合的Command物件

ADO.NET-SqlDataAdapter簡介(1)

在ADO.NET中,SqlDataAdapter所扮演的角色,其實是SQL Server(資料來源)與In memory資料庫(DataSet)的橋樑,SqlDataAdapter有四個屬性分別對應查詢、新增、修改、刪除的SqlCommand物件

1) SelectCommand屬性,功用為自資料來源擷取資料至DataSet裡的資料表
2) InsertCommand屬性,回寫資料來源前需設定
3) UpdateCommand屬性,回寫資料來源前需設定
4) DeleteCommand屬性,回寫資料來源前需設定

範例如下
*因篇幅關係,大部份程式碼略過

//SelectCommand結果填入DataTable
//cmd做為SelectCommand屬性
//dt為DataTable
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);

//回寫資料來源
//insCmd為一個以新增資料的SqlCommand物件
//updateCmd為一個以修改資料的SqlCommand物件
//delCmd為一個以刪除資料的SqlCommand物件
da.InsertCommand = insCmd;
da.UpdateCommand = updateCmd;
da.DeleteCommand = delCmd;
da.Update(dt);

在SqlDataAdapter物件做回寫至資料來源時,會引用DataTable物件,並依據每一筆資料列的DataRowState去對應到適合的SqlDataAdapter Command屬性

2009年7月14日 星期二

T-SQL切割字串另類方法

在SQL Server中並沒有提供類似Split的函數,所以在做字串切割時得自己撰寫自定函數或在Stored Procedure裡撰寫相關T-SQL語法,在這裡介紹一個SQL內建的函數PARSENAME,這個函數原本是提供傳回物件名稱的指定部份。物件的可擷取部份有物件名稱、擁有者名稱、資料庫名稱和伺服器名稱。底下是擷取SQL 2005的線上叢書的程式片段
USE AdventureWorks;
SELECT PARSENAME('AdventureWorks..Contact', 1) AS 'Object Name';
SELECT PARSENAME('AdventureWorks..Contact', 2) AS 'Schema Name';
SELECT PARSENAME('AdventureWorks..Contact', 3) AS 'Database Name;'
SELECT PARSENAME('AdventureWorks..Contact', 4) AS 'Server Name';
GO

結果集
Object Name
------------------------------
Contact

(1 row(s) affected)

Schema Name
------------------------------
(null)

(1 row(s) affected)

Database Name
------------------------------
AdventureWorks

(1 row(s) affected)

Server Name
------------------------------
(null)

(1 row(s) affected)

這個函數可接受的參數有二個,第一個參數是由四個piece所組成,piece與piece之間以.為連結符號,第二個參數是指要取得第幾個piece。現在我們將這個函數引用到其它的地方,下面的T-SQL片段,主要是將IP位地做切割
DECLARE @IP_Address VARCHAR(15)
SET @IP_Address = '192.168.0.1'
SELECT PARSENAME(@IP_Address, 4) AS piece4
SELECT PARSENAME(@IP_Address, 3) AS piece3
SELECT PARSENAME(@IP_Address, 2) AS piece2
SELECT PARSENAME(@IP_Address, 1) AS piece1

結果集
piece4
------------------------------
192

(1 row(s) affected)

結果集
piece3
------------------------------
168

(1 row(s) affected)

結果集
piece2
------------------------------
0

(1 row(s) affected)

結果集
piece1
------------------------------
1

(1 row(s) affected)

使用PARSENAME有幾個限制,第一個是參數1的組成必需小於等於四個piece,也就是說一個piece也行,第二個是參數2的值必需介於1~4的整數,所以當你的字串是由非常多的piece所組成可能就得自己寫自定函數,更詳細的資料請參考SQL2005線上叢書或sqlteam

2009年7月12日 星期日

WebChart介紹1

在資料呈現上高階主管總是希望一目瞭然,所以很多主管都希望下屬在報告時儘可能用圖形的方式來說明,然而在Visual Studio 2003&2005並沒有內建Chart的控製項(2008有Chart Control,但需要自行下載),下面是我目前所知道在ASP.NET下常用的Chart元件,但我並不會全部說明
  1. WebChart(dotNet 1.1可用,2.0以上未試過,是free元件)
  2. OWC
  3. Zedgraph(授權)
  4. Dundas(付費軟體,目前為Chart元件的領導廠商)
  5. Microsoft Chart Controls for .Net 3.5 (安裝至 .NET 3.5 SP1 才能正確使用該元件,控制項核心是微軟跟Dundas公司購買 Dundas Data Visualization 元件)
  6. Reporting Service(在ASP.Net嵌入Reporting Service報表檔的url)
接下來的幾天我會陸續介紹WebChart、OWC、Zedgraph、Microsoft Chart Controls for .Net 3.5 ,Dundas的元件是付費所以我不介紹,另外Reporting Service我也不介紹(我不喜歡以嵌入的方式來處理圖形)

2009年7月2日 星期四

ASP.NET匯出Excel時,指定欄位格式

在系統開發時,使用者通常會想要網頁提供匯出Excel的功能,在我們實作這個功能時常常會遇到格式的問題,譬如說在網頁上的手機欄位顯示是正常格式(09xxxxxxxx),但匯出Excel後居然變成9xxxxxxxx,底下的程式片段可避免格式跑掉
Response.Clear();
Response.Charset = "big5";
Response.AddHeader("Content-Disposition", "attachment;filename=myExcel.xls");
Response.ContentType = "application/vnd.ms-excel";
Response.ContentEncoding = System.Text.Encoding.GetEncoding("big5");
Response.Write("<html><body>");
Response.Write("<meta http-equiv=Content-Type content=text/html; charset=big5>"); //避免亂碼
Response.Write("<style type=text/css>");
Response.Write("td{mso-number-format:\"\\@\";}"); //將所有欄位格式改為"文字"
Response.Write("</style>");
Response.Write("<table>");
.
.
.
Response.Write("</table>");
Response.Write("</body></html>");
上方的程式碼片段是讓匯出的Excel檔儲存格格式強制為文字。那如果有部份欄位需要數字的儲存格式該如何處理?
Response.Write("<td style=\"mso-number-format:'0\\.0'\">"+欄位內容值+"</td>");
主要的做法就是利用css定義整個Excel欄位的格式,再利用td的style做覆寫,至於詳細的欄位格式,可以參考這裡

2009年6月22日 星期一

the pdf toolkit(pdftk)

今天向大家介紹一套免費的PDF工具 pdftk,為什麼會介紹這個軟體,因為它可以做command-line,所以我們可以將它整合在系統的Job或當做外部指令應用,底下是它所提供的功能
  • Merge PDF Documents
  • Split PDF Pages into a New Document
  • Rotate PDF Pages or Documents
  • Decrypt Input as Necessary (Password Required)
  • Encrypt Output as Desired
  • Fill PDF Forms with FDF Data or XFDF Data and/or Flatten Forms
  • Apply a Background Watermark or a Foreground Stamp
  • Report on PDF Metrics such as Metadata, Bookmarks, and Page Labels
  • Update PDF Metadata
  • Attach Files to PDF Pages or the PDF Document
  • Unpack PDF Attachments
  • Burst a PDF Document into Single Pages
  • Uncompress and Re-Compress Page Streams
  • Repair Corrupted PDF (Where Possible)
接下來我僅針對浮水印部份來做Demo說明
參與演出角色
  • pdftk.exe
  • 原稿PDF(取名為 in.pdf)
  • 浮水印PDF(取名為 back.pdf)
  • 產出後PDF(取名為 out.pdf)
首先我們來看原稿內容


浮水印內容


步驟1、我們將 pdftk.exe、in.pdf、back.pdf一併放置在C:\ 底下
步驟2、利用開始-執行鍵入cmd,進入命令提示字元
步驟3、在c:\ 下輸入 pdftk in.pdf background back.pdf output out.pdf


在這裡有關浮水印的參數有background及stamp,二者的差別在background會將浮水印放在合併後文件的下面,而stamp則會像郵票一樣貼在合併後文件的上面,更詳細的內容請點選這裡

2009年6月10日 星期三

Stored Procedure中為流水編號補0

在系統開發中有時需要產生一些流水編號,例如格式為yyyymmnnnn(2009060001),通常在產生新的流水編號前,我們會利用SELECT語法得出某個期間內的最後一個流水編號,以上面的格式來說,如果沒有200906開頭的流水編號,表示流水編號由1開始,相反地如果有則把流水編號加1,在這裡我只針對流水號補0來說明,底下有二段程式片段,第一段是一般寫法,第二段則是比較精簡的寫法
一般寫法
IF (LEN(@num) = 1)
BEGIN
   SET @num = '000' + @num
END
ELSE IF (LEN(@num) = 2)
BEGIN
   SET @num = '00' + @num
END
ELSE IF (LEN(@num) = 3)
BEGIN
   SET @num = '0' + @num
END

精簡寫法
SET @num = RIGHT(('0000' + @num), 4)

上面的寫法只是提供另一個思維,真正在撰寫時可能要考慮更多東西(例如資料型態的轉型)

2009年6月7日 星期日

去除字串最後一個逗號

在一些狀況下,我們可能需要傳送一連串的值給Stored Procedure,所以我們會在程式中串接字串,因為是用for-loop之類的方法,所以字串後面都會多個分隔符號,為了刪除最後一個分隔符號程式設計師大都會用String類別的一些方法去刪除,有些程式設計師會用Substring來處理,在這裡提供比較好的做法。

原本的程式
string mystring = "1,2,3,";
mystring = mystring.Substring(0, mystring.Length-1);

建議
string mystring = "1,2,3,";
mystring = mystring.TrimEnd(new char[]{','});

為什麼說TrimEnd是比較好的做法,因為要用Substring要加更多判斷條件
Substring如果沒有加判斷條件會發生一些狀況
  1. 當mystring = "1"; 時,用Substring則mystring最後值等於"" (理論上是"1");
  2. 當mystring = ""; 時,會發生System.ArgumentOutOfRangeException: 長度不可以小於零。

2009年6月5日 星期五

使用jquery全選/清除CheckBox

過去要在GridView的Header加入CheckBox的全選/清除功能,不外乎有二種做法,第一種是在Server-side做,也就是在.cs檔裡撰寫相關事件程式,第二種則是利用javascript撰寫Client端的程式,先取待Table的id (GridView的ClientID),再利用for-loop逐筆選取或清除。今天介紹一個方法(Client端做法)可以讓程式更簡潔
首先來看MasterPage(因為筆者的程式有引用MasterPage)的程式片段
<script type="text/javascript" src="../js/jquery.js">
<script type="text/javascript">
function SelectAllCheckboxes(chk) {
  <asp:literal id="litCheckAll" runat="server"/>
}

上方程式片段有二個重點
  1. 需嵌入jquery
  2. 要利用Literal控制項(因為Literal在產生Html碼時不會加入Html Tag)
接下來我們來看.aspx檔的程式片段
<HeaderTemplate>
  全選/清除
  <br />
  <asp:CheckBox ID="chkAll"
    onclick="javascript:SelectAllCheckboxes(this);" runat="server" />
</HeaderTemplate>

上方程式主要目的是要為GridView Header裡的全選/清除CheckBox加入onclick的事件

最後來看.cs檔的程式片段
if (!IsPostBack) {
//動態產生全選/清除的javascript function
//在MasterPage中已加入jquery的js檔
  ((Literal)Master.FindControl("litCheckAll")).Text = "$('#" + gvPlanList.ClientID + " >tbody >tr >td >input:checkbox').attr('checked', chk.checked);";
}

參考來源

2009年6月1日 星期一

.Net Reflector

有時候我們承接別人遺留下來的專案,看到密密麻麻的程式,心裡難免會罵一聲暗,如果程式只是一個執行檔(exe)又沒有source code,那絕對會想殺人,這裡介紹一個工具Red Gate's .NET Reflector,這個工具可以檢視.Net所撰寫的組件(dll)或執行檔(exe)的內容,首先底下是source code
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1 {
 class Program {
  static void Main(string[] args) {
   Console.Write("Hello World!");
  }
 }
}
這是一個簡易的主控台應用程式專案,專案輸出類型為類別庫(dll),接下來我們會利用Red Gate's .NET Reflector工具檢梘dll檔案的內容





希望對大家有些幫助

2009年5月24日 星期日

線上網頁編輯器FCKeditor(一)

寫這篇文章的動機,其實是來自過去一個同事所負責的專案有引用到,這篇文章談不上什麼教學,只是我參考網路並且自己實作上的一個紀錄。底下是引用FCKeditor的作法
首先下載
下載後將二個壓縮檔解壓縮,並將FCKeditor_2.6.4.zip解壓縮後的目錄拷貝至你所開發的ASP.Net Web專案

在ASP.Net Web專案中參考 FCKeditor.Net_2.6.3.zip解壓縮後的資料夾名稱\bin\Release\2.0\FredCK.FCKeditorV2.dll (如果專案為Visual Studio 2003
開發時,可選擇 1.1資料夾底下的FredCK.FCKeditorV2.dll)


在[工具箱]加入索引標籤 FCKeditor,點選[工具]再點選[工具箱項目],在[.Net Framework元件]頁籤中透過[瀏覽]將FredCK.FCKeditorV2.dll加入,此
時[工具箱]裡索引標籤FCKeditor中多了一個FCKeditor

修改ASP.Net Web專案內的web.config檔

value裡的值為拷貝至ASP.Net Web專案裡FCKeditor目錄的名稱。

修改fckconfig.js檔案(檔案位於fckeditor目錄下)
FCKConfig.DefaultLanguage= 'zh-cn'
_FileBrowserLanguage = 'aspx'
_QuickUploadLanguage = 'aspx'

大功告成,底下為執行畫面