查詢SQL Server可同時連接使用者人數上限

Yahoo站長工具裡,常看到有使用者找一個關於SQL Server的資訊,他們想知道SQL Server可同時連接SQL Server使用者人數。

其實只需要下個簡單的SQL語法即可,以下是在SQL Server 2008 Express執行的結果:


select @@Max_Connections


我回應的整數值為「32767」,也就是說在SQL Server 2008 Express這個版本,可同時連接的使用者人數為「32767」,很夠用了吧!個網站要同時有32767個連接,也是一件不簡單的事。

在「SSMS工具→物件總管→任一資料庫→可程式性→系統函數」之下,有許多實用的函數,如果你忘了指令名稱,也是個查詢的好地方,不想用打字的,也可以從這裡「拉」進去你*.sql之中。

Windows Vista 電腦上 HTTP 流量的「接收視窗自動調整」功能

我個人更新後,上網速度明顯加快(不知是否是心理作用),請認真看完說明,再決定是否安裝。

Windows Vista 電腦上 HTTP 流量的「接收視窗自動調整」功能

也推薦給各位使用「窗戶牌」作業系統的人,有空可多多上:http://support.microsoft.com,現在已經增加了許多有用實用的中文內容,能讓你在使用全球第一大「窗戶牌」時,更加得心應手,而且現在方便許多,都已經把「參數」給「工具化」,不會設定,沒關係,只要下載對應的更新工具,然後安裝,此工具包就會幫你把相關設定給設定上去,而且除了安裝外,還都有提供「復原」工具。

「設定」工具,是把相關設定給「新增」或「修改」;
「復原」工具,是把相關設定給「刪除」或「修改」;復原的修改是將設定修改回「原設定值」。

例如,我安裝了IE 8,但使用後,我想增加IE單次下載檔案的數量,就可以參考這一篇:

我要如何將 Internet Explorer 設定為一次下載兩個以上的檔案?

按下畫面上的「Fix it」下載工具,然後安裝、重開機(一般而言),就完成了,這樣簡單的動作,就可以簡單讓我在下載資料時,就是比人家快。

最後是,安裝之前,請接到畫面最下方都會有一個「適用於」的資訊,請確認你的環境是合乎這個適用於的環境,不然要是裝了出問題,我可不負責。

以上提供一些使用http://support.microsoft.com/的心得,裡面好東西很多,不過請記得你所設定過的東西,萬一你要復原也才知道要復原那一個。

[轉檔]購屋資訊

一些朋友給我關於「成為有殼人」的回應,買屋我是新手,但如果你想要有更進一步的資訊,我這裡有一份PowerPoint,可以提供給大家。

聲明:此檔案為Email轉寄所留存檔案,版權屬原作者所有。




請慢用。

SQL語法的不方便性

前端網頁與後端資料庫溝通,不外乎就是SQL語法,以前就一直覺得為什麼SQL語法設計的那麼差,沒錯,一點都沒有人性化在裡面,一看就知道是工程師計設的,尤其是看過及學過LINQ後,感覺才整個對了。

如果你使用SSMS管理工具來下SQL語法,它提供類似VS開發工具的提示功能,但你會發現如果你不先下「from語法」,那「select語法」或「條件語法」下起來會困難重重,尤其是select_list(欄位)很多,那可是會瘋了。

所以我個人習慣是這樣來下SQL語法:

select *
from customers

等下完from之後,再回去把「*」修改成我要的資料,然後再去下其他where條件等。我是學ASP.NET所以當我看到LINQ之後,非常高興,由from開始,由select結束。

你不先知道從那裡來(from),怎麼可能就知道會有什麼資料(select)?雖然常說,資訊科技一日千里,但回頭看看,還是有很多很慢的地方。大學第一次學SQL Server到現在,SQL語法都已經出來多久了,都沒有人想過去把它改人性一點。只是把語法上下換個位置,很難嗎?

LINQ真的是個好東西,我真的認為可以推廣到其他程式語言裡面,讓開發可以更快樂點,更人性點,不要每天看一堆寫一堆不人性的東西,都快變科學怪人了。

.NET Framework 除錯工具--DebugView

我們在寫程式時,很難,不,應該說不可能沒有除錯,目前的IDE開發工具都有不錯的語法除錯功能,而我們通常會使用一些技術來Debug,例如早期ASP時,使用

response.write("...")
response.end

來慢慢除錯,而且除錯完畢,還要記得把除錯程式碼移除,或是使用一個邏輯來偷放除錯程式;

if request("Debug") = true then
response.write("...")
response.end
end if 

而現在在.NET Framework裡,我們更可以使用Trace類別Debug類別來幫忙除錯。使用Trace只能用在開發環境,已上線服務不太可能讓你使用Trace;使用Debug類別我們在一般網頁又看不到訊息。

現在要來介紹一套sysinternals提供的工具,DebugView for Windows v4.76
以下是網站的介紹:
Sysinternals 的另一個首開先例:這個程式會攔截分別由 DbgPrint 利用裝置驅動程式,和 OutputDebugString 利用 Win32 程式所做的呼叫。它能夠在您的本機上或跨網際網路,在不需要作用中的偵錯工具情況下,檢視和錄製偵錯工作階段輸出。

這是一個不用安裝就可以使用的工具,在你的Windows作業系統執行後,你就會發現它已經開始抓取訊息,除了本機的訊息,它也能抓取遠端主機的訊息,很棒吧。

讓我們先設定一下:Edit → Filter,預設是"*",就是抓取所有相關訊息。讓我們修改一下,在include修改為「Bruce」。

新增一個DebugView.aspx,然後在DebugView.aspx.vb中新增程式碼:

Imports System.Diagnostics

Partial Class DebugView
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Debug.Write("Bruce: This is From Debug.Write message, 請查看你的DebugView工具")
    End Sub
End Class

先執行DebugView.exe,然後VS或本機IIS執行DebugView.aspx網頁,你就能清楚看到DebugView.exe正確過濾出訊息裡有Bruce的字串,而執行的DebugView.aspx是一片空白。這樣我們就能讓使用System.Diagnostics.Debug類別+DebugView程式來幫助我們提供必要的訊息,讓我們的開發之路更順利,而又免除把不必要的訊息顯示給一般使用者。

找回你忘記的密碼--MSN, Yahoo...

網路上的服務越來越多,而且麻煩的是每一個都需要帳號及密碼,好一點的可以使用我們自己想要的帳號及密碼,差一點的,就是要申請一組新的帳號及密碼,先測試你所要申請的帳號是否有人使用,如沒有,才能往下進行。最差的就是,想使用我的服務,還必須先申請一個全新的會員,新的Email、新的帳號、新的…,除非服務內容真的很好(如Google),不然這種方式真的讓人很不喜歡。

還有一些人在推OpenID技術,也就是一組帳號走透透,不過現在使用起來還不是很方便。

最近有位新進同事跟我反應,說他之前申請MSN帳號的密碼忘了,因為都使用自動登入,所以久沒Keyin就忘了,但最近他的NB電腦已經有不穩定,有點想重灌,但因為所有朋友名單都在MSN上,所以不敢重灌,問我有沒有辦法。

這種MSN, Yahoo…忘記密碼還蠻常發生,我自己也有過,因為「自動登入」真的很方便,但久沒Keyin來回憶一下,而且又沒有提供「找回密碼」或「重設密碼」也很麻煩,就算有,我這位新同事是使用之前公司Mail來申請的,所以找回密碼的信件,也是發到前公司,所以他很傷腦袋。

如果各位有這方面的煩腦,以下我推薦這個網站裡的工具:

http://www.nirsoft.net/utils/index.html#password_utils

這個網站裡有很多實用的工具,而且他每個工具都讓人家很方便來「語言化」,也就是說,他本身只推出英文版,其他語系的語言檔,都是透過網友的幫忙來翻譯,我之前也「自動幫忙」翻譯了一個工具的繁體中文檔。

在Password Recovery Utilities(密碼回復工具集)工具分類中有許多工具,我這次使用的是:MessenPass這一套,它本身目前支援以下IM聊天程式找回密碼的功能。


  • MSN Messenger
  • Windows Messenger (In Windows XP)
  • Windows Live Messenger (In Windows XP And Vista)
  • Yahoo Messenger (Versions 5.x and 6.x)
  • Google Talk
  • ICQ Lite 4.x/5.x/2003
  • AOL Instant Messenger v4.6 or below, AIM 6.x, and AIM Pro.
  • Trillian
  • Trillian Astra
  • Miranda
  • GAIM/Pidgin
  • MySpace IM
  • PaltalkScene
  • Digsby

基本上主流、非主流都支援的相當完整,而且我在下載時,防毒軟體還一直擋,說這是個「危險」程式,不讓我下載。我要在這裡提醒,這裡的工具是要「Recovery 回復」,說白一下,就是「找回」的動作,很多人會誤解為「破解」的動作。

在你要找回密碼的主機上,必須有使用過相關服務,而且完成登入過,所有在其他人的電腦主機上執行,當然你也能看到其他人主機上使用過的IM服務的帳號及密碼。所以自己的電腦還不是要隨便給人家用,尤其是我,不要叫我修電腦。@.@


後記

之前有位匿名的網友,想請我幫忙去破人家的Yahoo信箱,我和他聊了聊,請他不要想太多,我有提到,如果你有辦法「碰」到那個人的電腦,或許可以很快就可以破了,我說的就是以上的方法。刀可以拿來救人,也可以拿來殺人,看你怎麼用。

SQL計算月底日期

其實不難,以下列出分解動作:


--使用dateadd設定為現在日期的1個月後
select dateadd(month,1,getdate()) "1個月後是"
go

--以字串char(7)來取得年與月,2010/01
--並在尾端加上'/1',使字串成為2010/01/1
select convert(char(7),dateadd(month,1,getdate()),111)+'/1' "下個月1日的日期"
go

--將字串轉換為日期格式
select convert(datetime,(convert(char(7),dateadd(month,1,getdate()),111)+'/1')) "日期格式"

--下個月初減一日,就是這個月底
select DATEADD(day, -1, convert(datetime,(convert(char(7),dateadd(month,1,getdate()),111)+'/1'))) "月底日期" 


一步一步加上去,千萬不要心急。
另外以前在寫網頁有種需求,需要取得伺服器上的時間來進行一些工作,因為一般使用Javascript或ASP取得的是Client電腦的時間,所以還必須大費周章。


select CONVERT(char,getdate(),111) "日期", CONVERT(char,GETDATE(),120) "日期時間" 



其實只要使用SQL語法去取得Server的時間,然後轉換成字串,然後讓ASP去取得SQL丟出的時間就可以了。就不用怕Client修改本機時間,或本機時間不準。有時實在腦袋實在轉不過來,你現在解決不了的問題(一直在想,怎麼用ASP或Javascript來解決),其他地方已經幫你解決了。



提醒自己:讓ASP.NET專注在網頁,資料的事就交給資料庫來處理。

成為有殼人之買屋必殺技

記得很久以前,看過這樣的漫畫,有一個年輕男人,不知道什麼原因被插了一刀,然後這個男人就用盡全身的力氣做完他一生需要做完成的事情,從公司加班、下班去租A片、談戀愛、結婚、生小孩…到小孩長大、小孩結婚、到子孩滿堂,最後終於被那一刀給結束他的生命。
還有一篇是一個小嬰兒,不知道為什麼,出生後就從放到一個大炮裡被發射出去,然後就從小嬰兒一邊飛一邊長大,會爬、會走,長大換上衣服,開始上小學、中學、大學,然後上班、談戀愛、結婚、生子…從青年、中年、老年,還在一直飛,飛到最後,終點是一副棺材,飛了進去完成了他的一生。

(以上兩篇漫畫,如有網友知道出處,麻請跟我說一聲,我想轉貼,感謝。)

下面是YouTube上的動漫「人的一生」,也是很有意思。


回想從前,在經營傳銷的日子裡,非常在意「人生」這種事,每天可以說都在與人談人生,但如果沒有經營過傳銷,日子一天一天過,其實是不會太在意什麼人生不人生,反正每天就是上班、下班、上班、下班,假日不是睡覺就是回家,日子得過且過,不知道什麼叫人生。也是因為傳銷,慢慢了解原來我們也可以不同,可以更上一層樓,想法改變了,世界就變了。

你想過什麼樣的人生,不全然是100%由你自己決定,重要的是,你付出過什麼?你努力過什麼?為了這個目標你願意花多少的時間、精神?在失敗時,你是否能再站起來?別人不看好時,你是否依然相信自己?(離題了)

人類文化演進至今,我們一生中重要的階段已經被摸索的差不多了,就如上述的小故事或動漫一樣,你可以快速的Re-View,原來我的一生到目前為止就是這樣,那請你想想,在這些重要階段之間,你是否能加入一些精彩的回憶,加入一些不一樣的元素。如果能,那我非常的恭喜你,你擁有一般人所沒有的人生重要元素,如果不能,那我請你從現在開始,也為你的人生加入這重要元素:「精彩。」

你的人生精彩嗎?

新居落成

2009/11/15是我入住新居的日子,從小朋友、到長大成人,從談戀愛、交女朋友、買車子、結婚、生子…每個階段我都覺得我好幸運,幸運的是每個階段的酸、甜、苦、辣我都認真的嘗過,而每個階段的我也都順利的渡過,現在我來到了另一個階段,我,終於成為一個有殼人。
其實從小寶貝出生後,就一直有和婆婆討論房屋的事,只是過一天算一天,也沒有很認真的去看房子,而我們一家四口住在溫暖租來的房間裡,也很習慣了,但當小寶貝一天一天長大了,發現她開始會爬、她開始學走,這溫暖的小房間已經不夠讓小寶貝活動。而就在婆婆一次買菜的過程中,她看中了一間14年屋齡的房子,我前後也去看了三次,最後決定買了。

第一次買房子,其實什麼也不懂,反正房仲、代書交代什麼,我們照辦就是了,雖然是照辦,但重要的細節我們可沒有放過。

前房主基本上是傢俱全附,所以她留下了非常大量的東西,所以從我11/15號入住進去以來,每天晚上都打掃、整理凌晨二、三點,連續二週,真的是累爆了,還好沒有爆肝,不然就…黑白了。在打掃、整理過程,突然有了一種「得道」的感覺,原來…

人生沒有用不到的經歷

在國中、高中時,常常晚上跟大哥出去工作,那時我大哥是做水電工作,為了增加收入,所以晚上會接一些Case來做,而那時候的我也喜歡東跑西跑,讀書跟我的緣份還沒有到,所以白天睡覺比較實在,而且我大哥出社會早,所以在車上還會聽聽說些社會新鮮事,這對當時我這個毛頭小鬼來說,這些社會上的「時事」,比起堂上的「古事」吸引力實在大太多了。

對當時的我而言,做水電工真的是很幸苦,水電水電,就是房子裡跟水跟電有關的都是水電工來做。記得有一次晚上,大哥接到一個新Case,在宜蘭壯圍,那是一個新蓋二排透天社區,而我們施工的是入口處第一間,也因為是新蓋而且都還沒有人入住,所以我們可以在晚上進行一些很吵的工作,例如打牆、打地板…,而那天一我記像很深,我在三樓工作、大哥在二樓忙,做沒多久,大哥就上來三樓說,東西收一收,我們先回去吧,我正在奇怪工作都還沒做完,怎麼就要回家了,但我也沒有多問。

其實那一天的工作很不順,打牆要埋管路時,老是打到鋼筋,其他工作也好不到那裡去。就在我們開車離開工地不久的路上,我大哥就問我,你剛才在三樓有沒有聽到什麼聲音?我說有呀,一直都有聽到有我們工作用的工具掉落地上的聲音。我大哥聽聽後點點頭說,那房子有鬼。大哥說,他一直在二樓,沒有下去過放工具的一樓,而且整個社區晚上只有我們兄弟兩個人在工作,根本就沒有其他的人,而一樓一直不時傳來「不正常」的聲音,加上工作又不順,所以大哥就決定收拾工具快點回家。我是有聽過風吹的聲音被當成「哭聲」,但要把風吹的聲音當成「工具掉落地上的聲音」,這很難吧,而且一次要同時間兩個人都聽錯了,那就更不簡單了。

所以第二天,我們就買了一些冥紙、水果、餅乾去施工大樓拜拜,就說我們只是來施工,請讓我們把工作做完。第二天就更也沒有那奇怪的聲音,我和大哥也加快速度,在第二天就把工作完成,快快回家。

好了,鬼故事說完了,那與人生沒有用不到的經歷有什麼關係?

與鬼故事無關,自從入住新家,天天以打掃與整理渡日,聽雞鳴、看日出,是一個屬於自己的家,所有龜毛個性完全肆虐,尤其是在做一些水電類的工作時,拉線、整線、通水管…不知不覺我有了得道的感覺,原來現在我所使用的功夫都是那時候跟大哥學來的,每一個都是,突然了解原來那時的學習是為了二十幾年後自己的房子,如果把整個房子的整理工作外包給正牌水電工,那預計花個幾萬元,一張四個小朋友出走,十張就四十個小朋友出走,心會很痛,自己來,除了有點累,但成就感是非常高的。怎麼說,我也會是一個資訊水電工。

現在就行動

自己簽了名,讓自己成為有殼一族後,最常做的事就是叫身邊的朋友快點去花時間去看房子,不要跟我以前一樣一直租房子過日子,不過你是單身、初戀、熱戀、同居、分居、未婚、已婚…都應該快點讓自己成為有殼人。我們有一個很好的房東太太,三不五時都提醒我們有時間快點去買房子,不要一直跟他租房子,但實在她的房子住起來很有感情,也就慢慢忘了買房子的事,但還好有個小寶貝,讓我又想起來。

我身邊結婚又有一個小孩的朋友,如果問他們還要不在生一個,有70%以上會回答:…養不起…,但如果真的討論後我又發現養不起不是事實,原因很簡單,可能是「業者」太利害,可以讓這些爸爸、媽媽陷入恐慌之中,所以從小就讓小孩什麼都是「最好的」,奶粉要用最好的,尿布要用最好的,幼稚園一定要雙語、安親班、才藝班、心算班…不會輸在起跑點XYZ班,看了都…為這些小朋友搖頭,他們最保貴的童年。而父母親呢,也好不到那去,明明月收入又不是幾十萬,但也是吃好、用好、名牌,更甚者還好「住好」,交通點要好,生活機能要好、還要住的舒適…在父母什麼都要好,小孩什麼都要好的情況下,第二個,開什麼玩笑,我也沒辦法。量力而為,我喜歡大家庭,我喜歡有兄弟姐妹,雖然從小吵到大,但長大之後才知道那是增加長大後感情的另一種方法。(又離題了)

會勸朋友快點去買房子是有原因的,一是現在相對房價比較低,如果你不是失業人口,對房子的要求不是那怎的高,應該可以找到合乎自己的房子。二是租房子租在久都是別人的房子,但買房子,房貸交久了,房子就是自己的。以我自己為例,我原先租在約4-5坪的小房間,一個月房租,6000元左右,現在自己的房子使用坪數25坪,每個月房貸約7500左右,多1500元,但可使用的空間多5倍,三房、二衛、一廚。因為我希望空間大一點,價格低一點,所以我選擇離市區有一點距離,但又在交流道旁,所以交通又不會造成我的問題,就算騎機車也比現在還多十分鐘的路程,但房價跟新竹市中心、或竹北來比,可真的~差很大。

目前如果單身,也可以考慮小套房為目標,以合乎目前需求的房子為開始,一開始不要給自己太大壓力,可以用一般的333法則,以薪水的3分之1來交房貸,一樣的錢,拿給別人花,和買自己的房子「置產」,也是~差很大。買了房子後,就開始後悔,以前為什麼不會想,應該早點買房子的,白白拿錢給別人花那怎多年。

來吧,成為有殼一族。不用怕。

省錢必殺技

錢錢錢,這個時代什麼都要錢,這是個「利」字當頭世代,且要重要的是,在不景氣時,我們更要量入微出,增加收入,一般而言不簡單,網拍、擺地攤…我有個朋友星期假日上山賣早餐…賺的都是幸苦錢,那微出是否會簡單些?雖然我暫時無法量入,但總要想辦法微出,所以在住入新居前,我就一直在想辦法要減少支出,有短期也有長期,也算另一種成長,因為住別人的房子,根本不會去想這些,但住進自己的房子,連一滴水都是要從我的帳戶扣錢,那可是就要斤斤計較,所以這一次光簡省支出就學到不少東西。

必殺技一:購房費用--省錢

第一次購買房子,老實說我笨笨的,什麼都不太懂,還好平時有交一些朋友,以下資訊是房仲朋友跟我說的,不過這筆錢我沒有賺到,但我還是分享出來。

在買賣過程中,賣方和買方都是要付錢給房仲業者,每一家房仲業者的價格不同,這一點請在賣或買之前先問清楚,重點就在這筆錢身上,這筆錢是可以「殺價」的,以我們的房仲業者為例,是跟買方收成交價0.2%,請記得要跟你的「業務」殺價,錢給公司,公司再發獎金給業務,所以如果業務「阿沙力」的話,通常可以把獎金壓低或把獎金拿來直接貼給你,讓這筆費用可以更低。

還有過程中,還會有一些雜七雜八的費用,請業務一次跟你說清楚,列表出來,請不要客氣,請這位業務能自行處理就自行處理,不要再跟你拿錢。不然只不過騎個機車,帶兩、三趟路就有幾萬收入,讓我有點想轉行了@.@!

必殺技:「少付一毛錢,就是多賺一塊錢。」

必殺技二:房貸--省錢

這是購屋成本裡最大一筆金額,如果這裡不斤斤計較,那我會叫你是錢大爺、錢奶奶。代書會幫你問,但這是自己的房子,代書不會跟你一樣與銀行斤斤計較,代書問到一個差不多,還可以的,就會通知你說這家銀行與貸款利率好不好。因為答案我們都不滿意,所以房貸部份,我要先請你準備好「電話錢」,為什麼要準備好電話錢,因為你要打個十幾廿十通電話,打給誰,請直接打給銀行,就說你要房貸資料。現在要資料很方便,銀行會問你買那裡(準備地址或地號),要貸多少錢,銀行會先估價,然後過一、二天就會回電話給你,跟你報告能貸款的金額、利率等等。就我打電話的經驗,目前銀行房貸的成數都不會太高,約五成左右,好一點也才六成,所以在自備款部分請要有點準備。

如果你有「朋友」這個好東西,用處就很大。問到最後都,雖然有差強人意的答案,但實在沒有滿意的答案。這時經朋友的介紹,我們貸到利率相當低的房貸。如果你上網查,房貸資料相當多,什麼指數型、固定型、優惠型…真的不是給一般人看的,不然這些專員為什麼要考一堆證照。不過現在銀行都會在前幾個月給你非常低的利率優惠,一般來都3-6月不等,都差不多是在1.5x%~1.9x%都有,但從第7~12月,就會跳到2.1x%~2.5x%開始,再來從13~24月,會來到2.4x%~2.9x%,前二年大多都是被銀行設定不能開「清償證明」,這因為如此,前二年通常都會有比較低的利率。

清償證明就是把房貸交清的一張證明,在房貸未交清之前,房子的所有權是在銀行,所以如果你沒有清償證明,你是沒有辦轉過戶,所以在二年內就算你把房貸全部交清或轉貸,銀行也有權不開這張證明給你。

我老婆的大哥,現在的房貸利率是在3.x%,一聽到我們的利率,二話不說,馬上跟我們要電話,說他要轉貸。銀行對不同的客戶有不同的等級,500大、1000大、年收入、貸款金額,通常等級越高,利率越低,我們最後貸到的利率是人家貸款金額500~1000萬等級的利率,(1.x+i)利率固定20年,如果一個月差個500元,500元*240月=120000元。你帳口多12萬好不好,那你要不要多打幾通電話。

必殺技:「問、問、問,問銀行,問朋友。」

而且在與這些業務交往時,請放下裡子、面子、身段,沒辦法,你要求人家給你相當的優惠,請身子軟一點。讓他拿出最最最優惠的方案為止。為了你的口袋,請不要臉的要求。

必殺技:「哄你的業務,把他當小孩一樣。」

必殺技三:省電

收獲之前要先花錢,這個簡單,把原先房子裡傳統燈炮換下,換省電燈炮,一樣是省電燈炮,27W有250元一顆,23W有200元一顆,經過皮鞋成本後,我們找到27W 200元一顆,23W 150元一顆,而且大量買再打9折,這裡共花了我2千多元,希望這些燈炮能幫我省下超過2千元,我就很高興了,算是花點錢做做環保吧,不計較了。

必殺技四:省水

我說過:「連一滴水都是要從我的帳戶扣錢。」所以水當然要省。在考慮之後,我決定採用「3M 省水閥」,因為它最簡單,也很實用,只是使用起來要一段時間才能習慣用按的來開關水,有時還是會忘了去開關水龍頭的開關。我購買的是One-Touch系列,有兩種省水率,一種45%,一種84%,45%這一種可使用在冷熱水的水龍頭,84%這一種請使用在純冷水的水龍頭,這是我看了好久才分辨出來。費用上45%約260-300元,84%約340~400元。

這是個很不錯的發明。但省電、省水這兩個方面,都是要長期才能看到效果,所以目前為止,我是先支出來「投資」,但收益還不得而知。希望這種「真正」能對地球有幫助的科技發明,不是拿來發財用,而是真正回饋給社會。(我想太多了,不要理我。)

還有馬桶,這是除了洗澡外,平常用水量最大的地方,要省也很簡單,準備幾個保特瓶裝滿水,放到馬桶水槽裡就可以了,就我家的馬桶而言,每一次約可省下原本三分之一左右的水量。

其實原本我有去買馬桶省水開關,就是可以分大號與小號的開關,大號大水量,小號小水量,但換上去之後才發現不合,所以只好利用傳統方式來省點水。

必殺技五:電子帳單--省紙

買了房子了,最麻煩的是要辦水、電、瓦斯…等的「自動轉帳」,所以要跑一堆地方,台灣電力公司、台灣自來水公司、瓦斯管理處,除了自動轉帳外,目前電力公司和自來水公司都有推出電子帳單,新竹瓦斯管理處還沒有,反正所有能申請自動化的地方都順便申請就對了。

不過在電子帳單方面,我有一點問題,像這些銀行或水電公司,把原本要寄給我們的紙本帳單換成電子帳單給我們,如果沒有提供其他方便的線上交費機制,那說電子帳單做環保是假的,只是把印帳單的成本轉嫁到消費者身上,會這樣說,就是看到還是有不少人把電子帳單「印」出來,拿到便利商店交費,那有什麼不同?

這些銀行、電信、水電公司…省下來印紙本帳單、寄送的錢,也沒看到回饋到消費者的身上。(我又想太多)

必殺技六:地利--省錢

地圖圖片

「地段、地段、地段。」以上是投資房地產的六字真言,不過那是投資而言。像我是以自住為主,雖然希望有機會有能力能換更好一點的房子(人是貪心的),但還是要考慮一些地段上的方便性。

「宜蘭雨,新竹風」,我也真利害,不是住在雨多的地方,就是風大的地方。而我的新居又落在新竹風最大的地段,風大有個好處,就是冷氣吹的少,我在看這房子時,早、中、晚各去過一次,中午那一次是個30幾度的大熱天,雖然是個大熱天,不過風不斷從窗戶灌進來,很涼很舒服。這個是地利之便,讓我從輕鬆就可以把家裡最大筆電費的支出可以節省下來。

我愛散步,我喜歡寬廣的View,雖然不是在市中心或竹北一樣繁華,但最少不會一眼望出都是高樓,都是馬路,都是車。而有個離市區很近的快速道路,讓我不用擔心交通問題,要去國1,國3、市中心、竹北、園區…都很方便,晚上回家又不會塞車,重點是,房價又比這些熱鬧地區低許多,一樣的坪數在市中心或竹北買要三倍的價錢。這是我個人非投資地段的考量。

必殺技七:Cable+網路+數位電視--省錢

現代人每人都要被媒體轟炸,所以新居當然要申請第四台跟網路,第四台沒有什好選擇,反正地區的系統業務就只有那一家,而網路就讓我考慮許久,參考了Hinet、Seednet、Cable後,我決定申請第四台包套的組合,第四台+網路+數位電視,第四台每個月590元,網路+數位電視每個月700元,速率為10M/1M,這樣加起來每個月為1290元,基本上數位電視包含了所有第四台的頻道,別外加了很多有的沒的頻道,共100多台,看都看不完,更吸引我的是有高畫質(HD)的頻道,讓我好想衝去買一台支援高畫質42吋的新電視。

高畫質、高畫質,我要高畫質。(婆之聲:No~)

如果我單純申請第四台,再加其他家的網路,不論怎麼算都要拉高到1500元以上,例如第四台590元加Hinet 光世代 10M/2M 990元(兩年約),或第四台加Seednet方案,都沒有Cable業者的組合來的好,而且還有一個重點,跟Cable業者的合約是一年一約,也就是說,如果明年有更好更便宜的方案推出,我可以選擇換成其他方案,與電信或手機二年一約來比,這種一年一約的方式非常吸引我。

必殺技八:家用電話--省錢

家用電話也可以省錢,沒錯,而且「省很多」。雖然手機已經是必須品,但一般家用電話還是非常必須的,但我又不想要花月租費去中華電信租一個每個月可能只打一、二通市內電話的門號,而且我記得好像還要壓金(3000元,十多年前的印象),所以多方查詢比較之前,我又找到一個更棒的方案,070網路電話,目前主推的有遠傳家用電話節費盒,這個節費盒會提供一個070門號,這是一個可以撥出及撥入的070網路電話,這很象Skype-in服務,但Skype-in不能在台灣使用。而且剛好有同事(感謝Daniel,又是朋友幫忙)認識經銷商,可以拿到兩年免月租費的方案,還加送一組軟體070門號(節費盒是門號綁在硬體裡),同事本身有使用,他家裡還是使用1M/64K的網路速率,使用節費盒只會有一點點Delay,品質還可以接受,所以我想,在10M/1M的環境下,應該可以跑的很順才是,所以我就大膽的申請下去。

這樣我不僅僅省下每個月的月租費,打多少算多少,而且打市內、手機、國際還能有節費的效果。在我P4 2.0的電腦上,使用軟體070撥出至手機,cpu約使用50%,頻寬約上下各30K/bps,通話語音品質很不錯。不過這裡提醒各位一下,除非雙方都是070門號,目前070門號只合適「撥出」,請不要叫親朋好友打市話進來,因為撥入的電話費很貴,而這件事業者都不會跟你說,我想這是他們地下利潤來源,反正省給你的從其他人身上拿回來。

070 to 070:Free;

070 to other:節費;070 to 市話:1.6元/5分鐘;070 to 手機:3.3元/分(這與Skype差不多);070 to 國際:查表

cell phone to 070:網外費率;

市話 to 070:以中華電信的網頁來說明:http://www.cht.com.tw/PersonalCat.php?Module=Fee,Describe&CatID=113&PageID=2129

市話 to 070:一般時段 9.9元/5分(0.033元/秒)、減價時段13.8/10分( 0.023元/秒)[註:原以秒計費,為比較轉換為分]

市話 to 市話:一般時段1.6 元 /5 分、減價時段1 元 /10 分

9.9 / 1.6 = 6.1875,也就是說,如果你使用市話撥給070電話,會比平常多6倍費用,如果是減價時段,更差到13.8倍,這是當初我沒有想到的。

使用070軟體時,還發現一個問題,就是目前070軟體只支援很「舊」的作業系統,說白一點就只支援Windows XP,這是比較可惜的地方,現在Windows XP都已經買不到了,而且平心而論,現在還安裝Windows XP的電腦,絕大部分都是3~5年前的舊電腦,所以在未開視訊之下就已經吃了我p4 2.0的cpu 50%,如果我找個人來試試視訊+語音,我相信數據會不好看。除了作業系統支援度不好之外,軟體UI、操作還有許多可加強的地方,或許是還沒有利潤收入,所以還不會投入太多成本,不過就現在使用的Windows Vista或Windows 7而言,就不是一件好事,而且Windows Vista都已經出來幾年了,業者還無法更新版本,這是我比較不放心的地方。

不過,使用070軟體也是有其好處,就是可以帶著走,像安裝在Notebook、Netbook後,在現在上網越來越方便,或是透過3G、3.5G隨時線上(Always Online),這樣就可以把NB當成手機來使用,讓NB除了NB,還可以當超級智慧式手機(因為可以撥入,不像Skype在台灣無法In),這樣的Smart Phone應該是市面上Monitor最大,功能最強。只不過還是有上述的問題,只能在Windows XP上使用,如果可以在Windows 7執行,那加上觸控,Perfect!

目前軟硬雙管齊下,先試用一、二個月,看看效果如何,如果不錯,我還想把手機費率降低,現在365元,應該可以降到165元,每個月又可以多省下200元,反正我的手機也很少打,打也都只打網內,我也沒有續約的問題,希望能從070門號的身上多賺一些回來。婆婆的綁約了,還要等一年多。等一、二個月,應該會寫篇使用心得。

必殺技九:傢俱--殺很大

標題有點想改成「九殺真經」,這已經是最後一個殺很大必殺技,新居雖然前屋主留下了很多傢俱,我們家小倆口省下了不了錢,但還是有不合我們倆口味的東西,能送人的就送給親朋好友,這是讓我們唯一有萬級花費的地方,關於傢俱我只有一句話,「殺很大」,不殺你就當錢大爺、錢奶奶,我個人認為傢俱的價差很大,牌價6萬~8萬的東西,打個折就已經剩下2萬~3萬,不要被這樣的折扣嚇到,死別人不要死自己那四個小孩,請努力的殺,殺紅了眼為止。

如果你沒有殺價的天份,那我就直接介紹,我認為找了許多家傢俱行之後,認為還不錯,我最後也是這一家買。記得,請找他們的兒子、女兒談,再找爸爸談,媽媽可能是管帳的,所以價錢比較硬!(如果本人看到,我只是說實話)因為老婆很會殺+報錯價,我買的很高興,價格也很滿意,報錯價這種是可偶不可求。其實,有時候買東西是一種Feeling,他們家給我們的感覺還蠻合的。

[補充]我不知道女兒是否有男朋友,不過看得出來她是個很孝順的女兒(滿口爸爸經),言談中,好像還沒有對象,有興趣的人,請直接連絡他爸爸(開玩笑)!

賀順傢俱廣場
新竹市經國路一段187號
03-5316813、5316871


必殺技十:房貸資訊先偷跑


今天12月3日,早上碰到對面要上班的鄰居,鄰居劈頭就問「買多少?」我個人是很不喜歡回答這樣的問題,因為買了都買了,買貴買便宜,能改變嗎?所以我很隨便回答一個事先討論過的數字,這時這位鄰居馬上回答說:你們買那麼貴,當初你們的房主才買多少錢!

老實說,我很討厭這些人問的沒水準問題,或是比較級問題。我女兒剛出生時,每個人都問題都是:你們喝什麼奶粉?你們包什麼尿布?沒了,這些人永遠只關心奶粉、尿布,然後就開始比較,我女兒喝什麼,包什麼,我孫子喝什麼,包什麼,你們喝那什麼牌子,聽都沒聽過,包那什麼牌的尿布,為什麼不給她喝什麼牌、包什麼牌的比較好!夠了,我們要喝什麼牌,要包什麼牌我們的權利,一定要電視廣告的才能喝,才能包嗎,會不會管太多!(讓我抱怨一下)

不過就在這鄰居說出前房主的價錢時,讓我又有得道的感覺,也讓我可以補上這第十重武功。

必殺技:「偷跑,先取得房屋及房貸資訊。」

意思是說,如果你看中一間房子,但不知道如何出價,那你可以先準備地址,和你預計貸款金額,用必殺技二,馬上開始打電話問銀行。以我得到的資訊,銀行給我的貸款成數是原房主購買金額的7成到8成,你可以各家銀行願意的貸款金額推一下你現在房價是否合理。

例如,屋主開500萬,而你預計貸款400萬,但你怎麼問銀行最高都只願意貸款300萬,這樣你心裡就有個低,為什麼屋主的價錢和銀行願意貸給你的差那麼多?500萬的7成也應該還要有350萬才是,這時這你要考慮殺價、談判,把你取得的資訊來慢慢跟屋主談,讓自己是有利的。

像我有個房仲的朋友(阿達)就是很幫忙,因為我看中的房子不是他們公司的案子,但他還是很幫忙的把公司內部的資料調出來給我參考,讓我在談價格時才有個底。(朋友很重要)

最後補充一個必中必,如果當初我老婆聽我的用這個必中必,買到的價格只比屋主的買價多3萬9000元,是個算底價的不錯的法則,因為原屋主把所有必要成本(傢俱…)都加到我們身上,所以說,在房價部分我買的不漂亮,但還可以接受。

必中必:「金額*0.9*0.9=出價」

請不要客氣,多為自己想,多為自己口袋裡四個小朋友想,這讓我悟道所得的心得。

最後,提醒各位,雖然上談的都是錢、錢、錢,但家的價值是你所定義,我認識一些有錢人,家裡應該是「皇」字來形容,用什麼高級、貴氣…都太低俗,但都是給外勞住,好笑吧,但這是真的,突然覺得,在皇家當個外勞也不錯,當什麼水電工!

一個有愛的家,比什麼都重要,切記。

女兒的1,2,3,4,5,6,7,8,9,10

選了個好日子(2009/11/15)入住,婆婆全家人都來熱鬧一下,這一天發生了好多事,原本保母明琴大姐知道我們11/15是住在租屋的最後一天,一大早就帶我們去買菜,還交代要怎麼拜,還有每樣菜、水果代表的意義,魚不能吃完…買完菜,問了我婆婆一句,你會不會煮?這種大場面就不是婆婆上得了台面,好心的明琴姐笑笑的說,我就知道,然後就把菜拿進她們家的廚房,大火快炒,1個小時,一大桌的菜,讓我不管是拜拜或請婆婆全家人吃飯,都很有面子。

而這一桌的菜色,也讓我們一家三口人(不含小花),吃了快一週左右,才全部消化完畢,這是人家的好心,可不能用垃圾車來解決。

也是入住當天,晚上當大家都回家後,我和婆婆在整理東西時,就聽到剛滿周歲的女兒,自己一個人口中喃喃自語,她居然在念1,2,3,4,5,6,7,8,9,10,這句話我從出生時就開始跟她玩,當她還小時,每次只要她在哭,我在伸出手指頭,然後比1~10給她看,一邊念,一邊比,說也奇怪,只要看到我比1~10,她機會安靜下來。就在當下,我和婆婆兩眼對看,突然覺得,每個小孩都是天才,每個小孩的成長每天都讓人驚奇。看她在新居衝來衝去,邊衝邊念,興奮的樣子,還好,我買了個家。

我在想,這是妳要送給老爸老媽的禮物嗎,說:「謝謝爸媽,送給我一個溫暖的房子和家。」

朋友是一輩子的財產

以上感謝很多朋友的幫忙,最感謝的是車行老闆,從我讀書來到新竹,每一次搬家都少不了你和你的小發財,我保證,下一次我全部買新的,不在讓你幸苦了。你真的是我生命中黃金級貴人。其他千甲的鄰居、室友們,也感謝你們多年的照顧。陳媽媽(房東太太)我永遠記的妳那會醉人的燒酒雞,超大顆的肉粽,非常感謝。保母明琴大姐和柳哥,也是在我們生活上給我們許多照顧及幫忙,還常常找我們去你們家吃大餐,非親非故,但你們把我們當親人一樣,謝謝。還有在經營傳銷時結交的好朋阿達,希望你每個月都能簽約簽到手軟,每個月都能拿一張簽了1600萬的單子來給我看,感謝你一路相伴。還有我最愛的爸、媽及岳父、岳母,在我需要你們幫忙時,你們從不會說不,希望也以後也是這樣的一位爸爸,有你們真好。

大學畢業後,同學們大多回鄉、回家,其實留在新竹可以說沒有什麼朋友,但一路走來,非常感謝朋友的相伴,讓我走的不獨單,在我需要幫助時,都有人可以伸手幫忙。朋友是一輩子的財產,這是值得永續經營的事業。

公安軟體

對岸的上層,好像一直不放心網路,也一直想Control網路,也許是因為共產的關係,所以可以大膽要求,近來我們大陸的伺服器被要求安裝公安軟體:

http://www.huadunsoft.com/product_download.html

奇怪的是,怎麼沒有像之前那樣反彈,或許只要求安裝在伺服器上,而不是一般個人電腦之上,網民力量大,而我們小小公司的小小伺服器怎麼有力量跟祖國力抗,乖乖安裝吧!

jQuery, Visual Studio -- Microsoft Ajax content delivery network (CDN)

content delivery network (CDN,內容分散式網路),簡單來說,就是分散網路流量的一種機制,網路伺服器會去判斷你所在的位置,而將你導引到比較近的伺服器去,以加速網路處理速度及分散網路流量。

這種技術在「大型」網站使用相當頻繁,例如Yahoo、Google或台灣快速竄紅的facebook也是,例如,假設facebook的主要伺服器在美國,但facebook可以在全球五大洲各建構當地的伺服器,當我連線到facebook去時,facebook偵測到我是在亞洲地區,所以就把我導往亞洲的伺服器去,讓亞洲伺服器來幫我服務。

而如果你有開發網頁程式,應該很少人不會去用Google API,而我其中使用最多的就是載入jQuery的函式庫,這個服務本身就是Google所提供的CDN服務,利用Google的超大頻寬來幫我們的Client載入這些必要的Javascript函式庫。

而我們也知道,Microsoft在開發工具(VS2008/VS2010)裡對jQuery的支援度大大提升,而剛剛才發現一個由微軟提供的Ajax CDN服務,也就是微軟把它本身ajax及jQuery的JavaScript函式庫放到一個CDN服務上,讓我們也可以使用跟Google API來載入jQuery函式庫一樣,以很方便的方式來將微軟本身ajax函式庫或jQuery函式庫透過CDN網路讓Client快速的載入。

Microsoft Ajax content delivery network (CDN)


使用Microsoft Ajax CDN載入jQuery

<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.3.2-vsdoc.js" type="text/javascript"></script>

重點在src屬性,只需要把你想使用的函式庫指定給src屬性即可。目前使用起來感覺速度還很不錯,有一點點好像比使用Google API還快的感覺。可是有一點我比較擔心的,像Google API我要換版本,例如我想使用jQuery 1.2.6版本,Google API需要修改的程式碼就簡單的多,而Microsoft Ajax CDN就必須修改一堆src屬性,希望未能也能加強這一段。

注意我上述的說明,現階段只提供微軟ajax「本身」相關及jQuery,而且你在VS2008裡如果想要使用jQuery IntelliSense,還是必須在VS 2008上更新檔,然後在要使用的*.aspx嵌入jquery.js及*-vsdoc.js等兩個檔案,才有辦法使用。把Microsoft Ajax CDN當成載入jQuery的另一個備份選擇,是個很不錯想法。

Reference:
Microsoft ajax CDN Domain改名為aspnetcdn

三個單引號,讓你的程式碼更優

我們在「Visual Studio 2008中的JavaScript IntelliSense」裡有介紹一個「XML Code Comment, XML程式碼註解」的方式,而且如果你是使用C#(C Shap)在開發應用程式,那你會發現,C#也是使用此種方式在註解程式碼(或說Sub/Function/Class...比較準),而且C#是當檔案一產生時就產生預設空白註解內容,但使用VB是不會。

其實我們VB也是使用「類似」的方式,而VB是使用連續三個「'」(單引號)來產生XML程式碼註解,開啟任一*.vb檔案,在任一Sub/Function上方打上連續三個「'''」,你會發現Visual Studio 2008開發工具,自動幫你補上預設空白的註解內容:

''' <summary>
''' 
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>

而且param的部份,Visual Studio 2008還會自動去抓取你Sub/Function裡的參數,來產生。這些註解對程式維護的幫助必要性,不用再提,而且在使用工具產生程式碼說明文件時,會有很大的幫忙。三個單引號,讓你的程式碼可看性更優,學起來。

SqlCommand的非同步行程

我們在前一篇提到MARS的功能,讓我們在進一步來談談ASP.NET裡SqlCommand類別的非同步功能。在MARS我們說明在一個資料連線裡同時存取多個結果集。而非同步功能能讓使用者同時對資料庫送出數個各不相關的命令。如果兩者結合,那更是強大。

首先使用MARS我們必須先在連線字串裡啟用「MultipleActiveResultSets=True」,再來,我們要啟用ADO.NET的非同步功能,我們也必須在連線字串裡加入「Asynchronous Processing=true」。

ADO.NET-Asyn.aspx

以下我們將介紹三種非同步的方式。

<form id="form1" runat="server">
    <div>
        <asp:Button ID="Poll" runat="server" Text="輪詢(Poll)" /> 
        <asp:Button ID="bntWait" runat="server" Text="等待-單一表(WaitHandle)" />
        <br />
        <asp:Button ID="bntHandles" runat="server" Text="等待-兩資料表(WaitHandle) + MARS" />
        <br />
        <br />
        <asp:GridView ID="gvOrders" runat="server" Caption="Orders">
        </asp:GridView>
        

        <asp:GridView ID="gvOrderDetails" runat="server" Caption="Order Details">
        </asp:GridView>
    </div>
    </form>

ADO.NET-Asyn.aspx.vb


Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration

Partial Class ADONET_Asyn
    Inherits System.Web.UI.Page

    '使用MARS
    Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString)
    Dim strSQL As String = "select top 5 Customers.CompanyName , Customers.ContactName , Orders.OrderID ,Orders.OrderDate , Orders.RequiredDate, Orders.ShippedDate from Orders, Customers where (Orders.CustomerID = Customers.CustomerID) order by Customers.CompanyName, Customers.ContactName"

    Protected Sub Poll_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Poll.Click
        Dim cmd As New SqlCommand
        cmd.CommandText = strSQL
        cmd.CommandType = CommandType.Text
        cmd.Connection = conn

        conn.Open()

        '非同步結果
        Dim asyncResult As IAsyncResult
        '執行非同步
        asyncResult = cmd.BeginExecuteReader

        '非同步是否完成,不然停止1秒
        While Not asyncResult.IsCompleted
            System.Threading.Thread.Sleep(1000)
        End While

        Dim dr As SqlDataReader
        '取回非同步資料
        dr = cmd.EndExecuteReader(asyncResult)

        gvOrders.DataSource = dr
        gvOrders.DataBind()

        conn.Close()
    End Sub

    Protected Sub bntWait_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles bntWait.Click
        Dim cmd As New SqlCommand
        cmd.CommandText = strSQL
        cmd.CommandType = CommandType.Text
        cmd.Connection = conn 
        conn.Open()

        Dim asyncResult As IAsyncResult
        '等待碼
        Dim WHandle As System.Threading.WaitHandle
        Dim dr As SqlDataReader

        asyncResult = cmd.BeginExecuteReader
        '取得非同步等待碼
        WHandle = asyncResult.AsyncWaitHandle

        'WaitOne,等待完成
        If WHandle.WaitOne = True Then
            dr = cmd.EndExecuteReader(asyncResult)
            gvOrders.DataSource = dr
            gvOrders.DataBind()
            conn.Close()
        End If
    End Sub

    Protected Sub bntHandles_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles bntHandles.Click
        Dim cmd As New SqlCommand
        cmd.CommandText = strSQL
        cmd.CommandType = CommandType.Text
        cmd.Connection = conn 'MARS

        Dim odcmd As New SqlCommand
        odcmd.CommandText = "select * from customers where companyName = 'Alfreds Futterkiste'"
        odcmd.CommandType = CommandType.Text
        odcmd.Connection = conn 'MARS

        conn.Open() 'MARS: cmd, odcmd

        '非同步處理
        Dim orAsyncResult As IAsyncResult
        Dim odAsyncResult As IAsyncResult
        '等待碼陣列
        Dim WHandles(1) As System.Threading.WaitHandle
        Dim orDr As SqlDataReader
        Dim odDr As SqlDataReader

        '取得非同步結果
        orAsyncResult = cmd.BeginExecuteReader
        odAsyncResult = odcmd.BeginExecuteReader

        '取得等待碼(WaitHandle)
        WHandles(0) = orAsyncResult.AsyncWaitHandle
        WHandles(1) = odAsyncResult.AsyncWaitHandle

        '第一種:使用WaitAll
        ''等待全部「等待碼」完成
        'System.Threading.WaitHandle.WaitAll(WHandles)

        'orDr = cmd.EndExecuteReader(orAsyncResult)
        'odDr = odcmd.EndExecuteReader(odAsyncResult)

        'gvOrders.DataSource = orDr
        'gvOrders.DataBind()

        'gvOrderDetails.DataSource = odDr
        'gvOrderDetails.DataBind()

        '第二種:使用WaitAny

        For i As Integer = 0 To 1
            Dim WHIndex As Integer
            WHIndex = System.Threading.WaitHandle.WaitAny(WHandles)

            Select Case WHIndex
                Case 0
                    orDr = cmd.EndExecuteReader(orAsyncResult)
                    gvOrders.DataSource = orDr
                    gvOrders.DataBind()
                Case 1
                    odDr = odcmd.EndExecuteReader(odAsyncResult)
                    gvOrderDetails.DataSource = odDr
                    gvOrderDetails.DataBind()
            End Select
        Next

        conn.Close()

    End Sub
End Class

其實用心看,程式不難,而且與我們之前寫的ADO.NET程式還有點像。

輪詢(Poll)

我們先由輪詢(Poll)來看,由BeginExecuteReader來啟動非同步的動作,BeginExecuteReader會傳回一個IAsyncResult,然後判斷非同步是否完成(asyncResult.IsCompleted),如已經完成,使用EndExecuteReader(asyncResult)取回DataReader資料。

等待(WaitHandle)

在等待方法裡,過程差不多,只是多了一個「等待碼(asyncResult.AsyncWaitHandle),而且改由這個等待碼來判斷非同步是否完成,再接下去完成後面的動作。而WaitHandle.WaitOne()會等待單一非同步行程完成或逾時,WaitAll()會等待所有非同步過程結束,WaitAny()需要以陣列管理一個以上的等待碼,而且你必須為每個想要處理的等待碼個別叫用

在第三個按鈕裡我們看出MARS加上非同步的實用性,你可以同時發出「多個」Query而不用擔心。

ASP.NET中MARS(多重作用結果集)

MARS:Multiple Active Result Sets,多重作用結果集。

MARS能在同一條資料連線(SqlConnection)開啟一個以上的結果集,並讓你同時存取這些結果集。

讓我們回憶一下,我們撰寫資料庫的流程,

  1. 連線字串(SqlConnection)
  2. SQL定義(SqlCommand)
  3. 取回資料(DataReader, DataSet)
  4. 處理(...DataBind...)
  5. 關閉連線(Close)

不管怎麼寫,大多跳不出這幾個步驟,而如果同一個畫面,同時需要存取幾個DataReader,DataSet,同樣的東西你就要寫兩次,寫三次,這樣是非常沒有效率,這時就非常合適使用MARS技巧。也就是說,步驟1裡的SqlConnection可以同時間給多個SqlCommand來使用,或是說,你需要同時存取同一台Database Server裡的不同資料庫,那也非常合適使用這個MARS技巧。

MARS的設定也異常簡單,只需要在設定連線字串時加入「MultipleActiveResultSets=True」來啟用MARS功能即可。

我們來看一個實例,我們要輸出一個Orders資料表,然後在Orders裡又抓取Orders Details的資料來一起輸出。


無MARS的GridView查詢


以下範例我使用一個下拉式選單,來查詢北風Customers的資料,同時顯示兩個GridView。

GridView.aspx

Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration

Partial Class GridView
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not Page.IsPostBack Then
            Dim ddlconn As New SqlConnection(ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString)

            Dim ddlcmd As New SqlCommand
            ddlcmd.CommandText = "select distinct ContactTitle from customers"
            ddlcmd.CommandType = CommandType.Text
            ddlcmd.Connection = ddlconn
            ddlcmd.Connection.Open()

            Dim ddldr As SqlDataReader
            ddldr = ddlcmd.ExecuteReader

            ddlTitle.DataSource = ddldr
            '顯示文字所對應資料庫的欄位
            ddlTitle.DataTextField = "ContactTitle"
            '欄位值所對應資料庫的欄位
            ddlTitle.DataValueField = "ContactTitle"
            ddlTitle.DataBind()

            ddlcmd.Dispose()
            ddlconn.Dispose()
        End If
    End Sub

    Protected Sub ddlTitle_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlTitle.SelectedIndexChanged
        '使用DataReader
        Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString)

        Dim cmd As New SqlCommand
        cmd.CommandText = "select top 5 * from customers where ContactTitle=@ContactTitle"
        cmd.CommandType = CommandType.Text
        cmd.Connection = conn

        '參數設定
        Dim ContactParam As New SqlParameter
        ContactParam.ParameterName = "@ContactTitle"
        '需得選取的值
        ContactParam.Value = ddlTitle.SelectedValue
        cmd.Parameters.Add(ContactParam)
        cmd.Connection.Open()

        Dim dr As SqlDataReader
        'CommandBehavior.CloseConnection,DataReader自動Close
        dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)

        'DataTable可把DataReader當成資料來源
        'Dim drTodt As New DataTable
        'drTodt.Load(dr)

        '由DataTable傳回DataTableReader物件
        'Dim dtTodr As DataTableReader
        'dtTodr = drTodt.CreateDataReader

        'gvDR.DataSource = drTodt
        'gvDR.DataSource = dtTodr
        gvDR.DataSource = dr
        gvDR.DataBind()

        'drTodt.Dispose()
        'dtTodr.Close 
        cmd.Dispose()
        conn.Dispose()

        '使用DataTable
        Dim dtconn As New SqlConnection(ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString)

        Dim dtcmd As New SqlCommand
        dtcmd.CommandText = "select top 5 * from customers  where ContactTitle=@dtContactTitle order by customerid desc"
        dtcmd.CommandType = CommandType.Text
        dtcmd.Connection = dtconn

        '參數設定
        Dim dtContactParam As New SqlParameter
        dtContactParam.ParameterName = "@dtContactTitle"
        '取得選取值
        dtContactParam.Value = ddlTitle.SelectedValue
        dtcmd.Parameters.Add(dtContactParam)

        Dim dap As New SqlDataAdapter
        Dim dt As New DataTable
        dap.SelectCommand = dtcmd
        dap.Fill(dt)

        gvDT.DataSource = dt.DefaultView
        gvDT.DataBind()

        dap.Dispose()
        dtcmd.Dispose()
        dtconn.Close()
    End Sub
End Class

你可以看到在SelectedIndexChanged事件裡,我為了要讓兩個GridView顯示不同的資料,所以我必須開關三次SqlConnection(含下拉式控制項的那一次),但其實這是不必要的,接下來我們來看看MARS的使用。

Multiple Active Result Sets


MARS.aspx

<%@ Page Language="VB" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="System.Configuration" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    '全域連線物件
    '在連線字串中必須設定「MultipleActiveResultSets=True」
Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString)
    
    Protected Sub Page_Load(ByVal sender As Object, _
                    ByVal e As System.EventArgs)

        Dim cmd As New SqlCommand
        Dim OrdersReader As SqlDataReader
       
        cmd.CommandText = _
                " SELECT TOP 5 Customers.CompanyName, Customers.ContactName, " & _
                " Orders.OrderID, Orders.OrderDate, " & _
                " Orders.RequiredDate, Orders.ShippedDate " & _
                " FROM Orders, Customers " & _
                " WHERE Orders.CustomerID = Customers.CustomerID " & _
                " ORDER BY Customers.CompanyName, Customers.ContactName "

        cmd.CommandType = CommandType.Text
        cmd.Connection = conn

        conn.Open()
        OrdersReader = cmd.ExecuteReader()

        gvOrders.DataSource = OrdersReader
        gvOrders.DataBind()

        conn.Close()
    End Sub

    ' RowDataBound事件處理常式
    Protected Sub gvOrders_RowDataBound(ByVal sender As Object, _
                 ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)

        Dim OrderRecord As IDataRecord
        Dim lblOrderDetail As Label

        '從e(DataReader)取得現在連繫的記鍵
        '轉換為IDataRecord interface
        OrderRecord = CType(e.Row.DataItem, IDataRecord)

        '從GridView物件找到Label控制項
        'Label控制項在Order Details裡面
        lblOrderDetail = CType(e.Row.FindControl("lblOrderDetail"), Label)

        If OrderRecord Is Nothing Or lblOrderDetail Is Nothing Then
            Return
        End If

        Dim cmd As New SqlCommand
        Dim OrderDetailReader As SqlDataReader
        cmd.CommandText = _
                "SELECT Products.ProductName, [Order Details].UnitPrice, " & _
                " [Order Details].Quantity, [Order Details].Discount " & _
                " FROM [Order Details], Products " & _
                " WHERE [Order Details].ProductID = Products.ProductID " & _
                " AND [Order Details].OrderID = " + _
                Convert.ToString(OrderRecord("OrderID"))
        cmd.CommandType = CommandType.Text

        '在連線字串中必須設定「MultipleActiveResultSets=True」
        'MARS:Multiple Active Result Sets,多重作用結果集
        '注意這裡,我們使用的是同一條SqlConnection來連線,也就是MARS作用所在
        cmd.Connection = conn

        OrderDetailReader = cmd.ExecuteReader()

        While OrderDetailReader.Read()
            lblOrderDetail.Text += OrderDetailReader(0).ToString() + "
"
        End While

    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>MARS範例</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="lblCounter" runat="server">
        <br />
     
        <asp:GridView ID="gvOrders" runat="server" AutoGenerateColumns="False" OnRowDataBound="gvOrders_RowDataBound" Width="100%">
            <Columns>
                <asp:BoundField HeaderText="Company Name" DataField="CompanyName"></asp:BoundField>
                <asp:BoundField HeaderText="Contact Name" DataField="ContactName"></asp:BoundField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        Order Detail
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="lblOrderDetail" runat="server">
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField HeaderText="Order Date" DataField="orderdate" DataFormatString="{0:d}">
                </asp:BoundField>
                <asp:BoundField HeaderText="Required Date" DataField="requireddate" DataFormatString="{0:d}">
                </asp:BoundField>
                <asp:BoundField HeaderText="Shipped Date" DataField="shippeddate" DataFormatString="{0:d}">
                </asp:BoundField>
            </Columns>
        </asp:GridView>
        <br />
        <br />
    </div>
    </form>
</body>
</html>

範例的重點在71裡RowDataBound事件裡使用同一個SqlConnection物件來連接。MARS在你需要同一Web Form裡需要使用越來越多結果集時,你就可以發現MARS的效果,讓我們的程式更有彈性,更靈活。

警告! www.seednet.net.tw 並不是合法主機!

看圖說故事。我的眼睛應該沒有問題?
如果「它」不合法,那我上的是什麼網站?


SqlDataAdapter類別,批次更新屬性

SqlDataAdapter類別,是我們在學習ASP.NET資料庫裡兩大支柱的其中之一,會使用到它,也是因為要對Data進行操作,才會考慮使用到它,不然如果是單純取得資料,那一定是考慮SqlDataReader

但我們在使用SqlDataAdapter類別更新」資料時,有一個屬性非常重要,但也是大多沒有介紹,「UpdateBatchSize 屬性」,也是就是,我們原先如果更新了100筆資料,那就會一筆Update Query,一筆Update Query來對資料庫做更新資料的動作,這樣的方式不但沒有效率,又浪費資源,但這個UpdateBatchSize 屬性,能讓我們改變SqlDataAdapter類別的行為,讓我們使用「批次」的方來更新資料,但如我們有一個dap的SqlDataAdapter實體,所以我們可以設定「dap.UpdateBatchSize=10」,以10筆資料為一個單位來更新,經過這樣設定後,原本需要100次Query,只批次簡化為10次Query就結束了。

而相較於單一Query的更新方式,UpdateBatchSize當然可以大幅改善效能。而UpdateBatchSize的預設值正是1,而如果我們設定為0,那SqlDataAdapter物件會一次處理所有的Update命令

也請小心,不要將UpdateBatchSize設的太大,每種資料庫批次處理的能力不同,上線前可多多測試,找出一個合理值,如果超出資料庫處理能力,SqlDataAdapter會拋出例外。

SqlBulkCopy類別,大量複製資料從A到B

昨天已經說了一個豬頭的故事,那今天就來寫個不豬頭的程式碼。

Default.aspx
<form id="form1" runat="server">
<div>
<asp:button id="btnBulkCopy" runat="server" text="Start Bulk Copy"></asp:button>
<asp:label id="lblResult" runat="server">
<asp:label id="lblCounter" runat="server">
</div>
</form>

Default.aspx.vb

程式目的:將程式本機資料庫中Share的資料大量複製到遠端Northwind資料庫中。

Imports System.Data
Imports System.Data.SqlClient

Partial Class _Default
    Inherits System.Web.UI.Page

    Protected Sub btnBulkCopy_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnBulkCopy.Click
        '程式本機 Database Server Connection String
        Dim shcs As New SqlConnectionStringBuilder
        shcs.DataSource = ".\SQLEXPRESS"
        shcs.InitialCatalog = "Share"
        shcs.UserID = "bruce"
        shcs.Password = "123456789"

        '遠端Database Server Connection String
        Dim ntcs As New SqlConnectionStringBuilder
        ntcs.DataSource = "192.168.3.12\SQLEXPRESS"
        ntcs.InitialCatalog = "Northwind"
        ntcs.UserID = "bruce"
        ntcs.Password = "987654321"

        Dim shcmd As New SqlCommand
        Dim shdr As SqlDataReader

        Dim shconn As New SqlConnection(shcs.ConnectionString)
        shcmd.CommandText = " SELECT ID, First_Name, Last_Name, 'CEO' as Source FROM MailingList"
        shcmd.CommandType = CommandType.Text
        shcmd.Connection = shconn
        shcmd.Connection.Open()

        '與遠端建立SqlBulkCopy實體
        Dim ntbcp As New SqlBulkCopy(New SqlConnection(ntcs.ConnectionString))
        '指定遠端的資料表名稱
        ntbcp.DestinationTableName = "Employees"
        '本機與遠端的Column對應,如本機與遠端的Schema一樣,可省略ColumnMappings
        ntbcp.ColumnMappings.Add("ID", "EmployeeID")
        ntbcp.ColumnMappings.Add("First_Name", "FirstName")
        ntbcp.ColumnMappings.Add("Last_Name", "LastName")
        '自定義欄位,把Source對應到Employees的Title欄位,所有欄位都會等於CEO
        Dim TitleMapping As New SqlBulkCopyColumnMapping("Source", "Title")
        ntbcp.ColumnMappings.Add(TitleMapping)
        'TimeOut,單位秒
        ntbcp.BulkCopyTimeout = 360
        '多少筆發一次通知
        ntbcp.NotifyAfter = 1000

        '委派
        AddHandler ntbcp.SqlRowsCopied, AddressOf OnSqlRowsCopied
        'AddHandler ntbcp.SqlRowsCopied, New SqlRowsCopiedEventHandler(AddressOf OnSqlRowsCopied)

        shdr = shcmd.ExecuteReader

        Try
      '執行WriteToServer,把本機資料(DataReader)大量複製到遠端資料庫
            ntbcp.WriteToServer(shdr)
        Catch ex As Exception
            lblResult.Text = ex.Message
        Finally
            shdr.Close()
        End Try
    End Sub

    Private Sub OnSqlRowsCopied(ByVal sender As Object, ByVal args As SqlRowsCopiedEventArgs)
     '由於ntbcp.NotifyAfter的關係,每1000筆觸發一次
        lblCounter.Text += args.RowsCopied.ToString() + " rows are copied.
"
    End Sub
End Class

程式流程不會很難,

  1. 建立本機SqlConnection實體
  2. 建立遠端SqlBulkCopy實體(使用遠端Sqlconnection實體)
  3. 執行本機ExecuteReader方法,取得資料
  4. 執行SqlBulkCopy實體的WriteToServer方法,將DataReader寫到遠端Server去

委派那一段可寫可不寫,在複製過程會觸發OnSqlRowsCopied事件,主要目的是顯示訊息讓使用者了解目前的進度。

如果兩端網路連線速度沒問題的話,十萬筆資料,都能在幾秒之內「秒殺~秒殺~秒殺~秒殺~秒殺~秒殺~秒殺~」,寫十萬筆Insert,有SqlBulkCopy不用,發瘋嗎。

ASP.NET WebForm命名注意

昨天在寫一支SqlBulkCopy類別的程式,說實在,這個類別可以寫的很簡單,也可以寫的很複雜。(廢話)

先簡單介紹一下,這個類別是.NET Framework 2.0所提供的一個類別,看命名就知道是在做「大量複製」,一般而言,例如,我們每一筆Insert就會對資料庫發出一筆Query,所以如我之前不是使用匯入方式來新增資料,而是使用複製、貼上就會浪費許多時間。

你簡單想像,SqlBulkCopy類別,就是「程式版的匯入功能」,讓你可以從多樣的資料來源,將你需要的大量資料批次匯入目的地資料庫

但今天我不是要介紹SqlBulkCopy類別的功能,而且我在寫的這支程式,非常奇怪,不論我怎麼宣告,Dim ntbcp As New sqlBulkCopy(ConnectionString),就是會跑出來「Public Sub New()的引數太多」的錯誤訊息,查了許久,實在想不出什麼原因,上網也找不到什麼可參考的資料,所以就上MSDN請教大內高手。

在來回幾次後,終於發現問題,豬頭是自己產生的。我是豬頭。

我新增的網頁名稱為「sqlBulkCopy.aspx」,所以產生了「Partial Class sqlBulkCopy」(s小寫),所以在程式中引用到自己(Web Form)的Class,而不是System.Data.SqlClient中SqlBulkCopy(S大寫)類別,所以當然有問題。

這也給自己一個經驗,
  1. .NET Framework類別,最好不要(一定不可以)拿來命名為網頁名稱
  2. 當局者迷。

使用SqlConnectionStringBuilder類別快速建立資料庫連線字串

我們ASP.NET網頁時,很少不用寫資料庫程式,而除了使用DataSource控制項外,如需要「靈活彈性」的話,那就不是DataSource控制項能提供了,所以等玩DataSource控制項一段時間後,還是不免要自行撰寫程式碼,而在寫資料庫連線程式時,常常會找筆記或參考程式複製、貼上那一段長長長長的ConnectionString,因為那一段ConectionString是字串,包在""之中,所以IntelliSense不會出現任何提示,你少打了一個字,打錯了一個字,也只能在執行網頁時才能除錯。也因為太長了,除非你天天打,打到都會背了,不然我看很少有人會去背那堆的參數。

其實在ASP.NET 2.0時就有提供一個非常好用的SqlConnectionStringBuilder類別,光看名子就知道,這是讓你拿來建立SQL連線字串,使用起來非常直覺,而且又提供IntelliSense,相信我,這可是能減輕腦負擔的好東西,如果你使用過一次SqlConnectionStringBuilder類別,大概就不會想回頭了,再去愛別人了。

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    '以下範例程式,未使用import System.Data.SqlClient
        '原始:Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;User ID=bruce;Password=123456789
        '以下使用SqlConnectionStringBuilder類別來建立ConnectionString
        Dim CSBuilder As New System.Data.SqlClient.SqlConnectionStringBuilder
        CSBuilder.DataSource = ".\SQLEXPRESS"
        CSBuilder.InitialCatalog = "Northwind"
        CSBuilder.UserID = "bruce"
        CSBuilder.Password = "123456789"
        CSBuilder.PersistSecurityInfo = True

    'CSBuilder.ConnectionString取得連線字串,建立SqlConnection
    Dim conn As New System.Data.SqlClient.SqlConnection(CSBuilder.ConnectionString)
    'Other Code
    End Sub

這麼好用的東西,你在市面上一般的書本中是看不到哦,學起來,根本就不用背任何東西,IntelliSense選一選就完成了,不過,必要的資訊(就是後面的字串內容)還是要記一下。

Microsoft Visual Studio International Feature Pack 2.0--在ASP.NET實作繁簡轉換

先看微軟的介紹:

Visual Studio International Feature Pack 2.0 擴充了先前 1.0 版的功能, 它提供了一組控制項和類別庫以幫助.NET開發人員建立符合國際化需求的應用程式。
跟我們之前介紹使用資源檔的方式不同,它提供的是控制項(Controls)和類別庫(Class Library)來幫助.NET開發人員處理各種亞洲語系上的的文字、字串處理工作。

而Visual Studio International Feature Pack 2.0是「擴充」之前1.0的功能,所以本身不含1.0的功能,如果想使用1.0提供的功能,可下載1.0進行安裝。

Microsoft Visual Studio International Pack 1.0 SR1
Microsoft Visual Studio International Feature Pack 2.0

如果你的網頁需要處理多國語言的問題,尤其是亞洲這個雙字元文字的問題,可一定要好好玩玩這個佛心級工具。想想,以前光一個「繁體轉簡體」的問題,就不知要花多少力,現在簡單幾行程式就可以完成了,.NET Framework是的越來越強大,真的是越來越愛了。

在Visual Studio International Pack 1.0 SR1的版本裡,我比較有興趣的是,CHTCHSConv.msi及EANumFormat.msi,

CHTCHSConv.msi
Traditional Chinese to Simplified Chinese Conversion Library and Add-In Tool (中文繁簡轉換類別庫 及Visual Studio Add-In Tool工具):提供了一組類別庫以幫助程式開發人員在應用程式中轉換將中文繁體至中文簡體(或是中文簡體至中文繁體). 此轉換機制使用的內建於 Microsoft office 2007 的程式, 它的以進行詞對詞的轉換, 讓轉換的品質更好. 若使用者的系統中沒有安裝Microsoft office 2007 , 此類別庫將使用傳統的字對字轉換. 除此之外, 此元件也包括了一個 Visual Studio Add-In Tool 工具可以讓使用都直接轉換存在於資源檔中的中文字串.
安裝後,將「C:\Program Files\Microsoft Visual Studio International Pack\Traditional Chinese to Simplified Chinese Conversion Library and Add-In Tool」之下的「ChineseConverter.dll」參考或複製到「Bin」目錄之下即可。

實作ChineseConverter

TCtoSC.aspx
<form id="form1" runat="server">
<div>
<asp:textbox id="tbxTCtoSC" runat="server"></asp:textbox>
<asp:button id="btnTCtoSC" runat="server" text="繁體轉簡體">
<asp:label id="lblTCtoSC" runat="server"></asp:label>    
<asp:textbox id="tbxSCtoTC" runat="server"></asp:textbox>
<asp:button id="btnSCtoTC" runat="server" text="簡體轉繁體">
<asp:label id="lblSCtoTC" runat="server"></asp:label>
</asp:button></asp:button>
</div>
</form>

TCtoSC.aspx.vb
'繁簡轉換命名空間
Imports Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter
Partial Class Test_TCtoSC
    Inherits System.Web.UI.Page

    Protected Sub btnTCtoSC_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnTCtoSC.Click
        If Me.tbxTCtoSC.Text.Length > 0 Then
            Dim TWString As String = Me.tbxTCtoSC.Text
            '使用ChineseConverter.Convert方法
            '第一個參數是你要轉換的字串
            '第二個參考是你要轉換目的語言
            'TraditionalToSimplified是繁體轉換成簡體
            Me.lblTCtoSC.Text = ChineseConverter.Convert(TWString, ChineseConversionDirection.TraditionalToSimplified)
        End If
    End Sub

    Protected Sub btnSCtoTC_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSCtoTC.Click
        If Me.tbxSCtoTC.Text.Length > 0 Then
            Dim SCString As String = Me.tbxSCtoTC.Text
            '使用ChineseConverter.Convert方法
            '第一個參數是你要轉換的字串
            '第二個參考是你要轉換目的語言
            'SimplifiedToTraditional是簡體轉換成繁體
            Me.lblSCtoTC.Text = ChineseConverter.Convert(SCString, ChineseConversionDirection.SimplifiedToTraditional)
        End If
    End Sub
End Class

以上這支程式還可以用我們之前介紹使用Button裡的CommandName及CommandArgument來改寫。

EANumFormat.msi
East Asia Numeric Formatting Library (亞洲語系的數值字串格式化類別庫):East Asia Numeric Formatting Library 提供了一組類別庫以幫助程式開發人員將數值資料格式化成亞洲語系的數值字串. 支援的亞洲語系包括了繁體中文, 簡體中文, 日文以及韓文.

將「C:\Program Files\Microsoft Visual Studio International Pack\East Asia Numeric Formatting Library」目錄之下的「EastAsiaNumericFormatter.dll」參考或複製到「Bin」之下。

實作EastAsiaNumericFormatter

EastAsiaNumericFormatting.aspx
<form id="form1" runat="server">
<div>
<asp:textbox id="tbxNumber" runat="server" tooltip="請輸入整數,例如:12345"></asp:textbox>
<asp:button id="btnNumToChinese" runat="server" text="數字轉中文">    
<asp:label id="lblNumtoChinese" runat="server"></asp:label>
<asp:label id="lblNumtoJP" runat="server"></asp:label>
</asp:button>
</div>
</form>

EastAsiaNumericFormatting.aspx.vb
'亞洲數字格式命名空間
Imports Microsoft.International.Formatters
'為了設定日文需要使用CultureInfo("ja")
Imports System.Globalization
Partial Class Test_EastAsiaNumericFormatting
    Inherits System.Web.UI.Page

    Protected Sub btnTCtoNum_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnNumToChinese.Click
        If Me.tbxNumber.Text.Length > 0 Then
            Dim ChangeNumber As Integer = Convert.ToInt32(Me.tbxNumber.Text)
            Try
                '會依瀏灠器做CultureInfo的選擇,如簡體瀏灠器則出現簡體中文的數字
                Me.lblNumtoChinese.Text = String.Format(New EastAsiaNumericFormatter(), "數字的中文是:{0:L}", ChangeNumber)
                '指定轉換的文字
                'Me.lblNumtoJP.Text = "數字的日文是:" & EastAsiaNumericFormatter.FormatWithCulture("L", ChangeNumber, Nothing, New CultureInfo("ja"))
                'FormatWithCulture(String, Object, IFormatProvider, CultureInfo)
                Me.lblNumtoJP.Text = String.Format("數字的日文是:{0}", EastAsiaNumericFormatter.FormatWithCulture("L", ChangeNumber, Nothing, New CultureInfo("ja")))
            Catch ex As Exception
                Me.lblNumtoChinese.Text = "錯誤:" & ex.Message
            End Try
        End If
    End Sub
End Class

在Microsoft Visual Studio International Feature Pack 2.0的NumericConversion,新增對阿拉伯文的支援,安裝到可到「C:\Program Files\Microsoft Visual Studio International Feature Pack 2.0\NumericConversion」之下將「InternationalNumericFormatter.dll」參考或複製到「Bin」目錄之下,新增「InternationalNumericFormatter」類別,可進行對阿拉伯數字字串的設定。

舉個例子,以下是我的想法,我還沒有實作,但應該可行。
使用WebRequest類別將網頁資料讀進來,然後透過上述方法去轉換內容,然後再輸出,看你是要繁轉簡或簡轉繁,應該都不成問題才是。


工具給各位,怎麼用就看各位的功力了,拿別人的努力讓自己更上一層樓。加油。

FileUpload中MIME

以下為MSDN中的MIME

Known MIME Types

text/richtext
text/html
audio/x-aiff
audio/basic
audio/wav
image/gif
image/jpeg
image/pjpeg
image/tiff
image/x-png
image/x-xbitmap
image/bmp
image/x-jg
image/x-emf
image/x-wmf
video/avi
video/mpeg
application/postscript
application/base64
application/macbinhex40
application/pdf
application/x-compressed
application/x-zip-compressed
application/x-gzip-compressed
application/java
application/x-msdownload

MIME常用在檔案上傳(FileUpload控制項),我們需要判斷檔案是否是我們要的類型,例如,我們希望使用者只能上傳zip檔:

IF FileUpload1.HasFile Then
  try
    IF FileUpload1.PostedFile.ContentType = "application/x-zip-compressed" Then
    'Code
    End IF
  '...
End IF

或是在傳送Mail(System.Net)時的附加檔案,總不希望使用者亂上傳資料檔案,所以就需要MIME來判斷,總之如果你需要資料使用者上傳了什麼東東,就需要使用MIME就對了。

參考:

ASP.NET控制Meta Tags

你或許使用過ASP.NET的Page.Title來修改網頁的標題,但你有沒有試過使用ASP.NET來修改Meta,你或許會說,那還不簡單,使用Page.Meta就好了,嗯!你打打看。

其實沒有那怎難,在ASP.NET中,除了控制項,我們還可以把一般的HTML轉換為HTML控制項,在ASP.NET中每一個HTML控制項都有對應的類別,例如,在Visual Studio中打「Dim meta As New html」你就可以看到所以html對應的類別,如HtmlAnchor對應的就是&lt;a>。

但如果我們想在程式碼中操控這些HTML,那就先必須把這些HTML轉換為ASP.NET的控制項,轉換的過程異常簡單,只需要在HTML Tags裡加上「runat="server"」屬性馬上就能將HTML轉換為ASP.NET的控制項。就我們的需求,我想要操控Meta所以我幫Meta加上兩個屬性:

<meta id="metaName" runat="server" />

這樣就馬上讓meta成為ASP.NET的控制項,而id是為了讓我們可以在程式碼中進行設定。

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        metaName.Attributes("name") = "author"
        metaName.Attributes("Content") = "Bruce"
    End Sub

這樣讓meta可進行程式碼操作後,就可以進行許多事,例如我們的動態頁面裡的meta可以與資料庫互動,動態產生meta,來進行簡易meta的SEO動作。

一樣的原理,可以用於其他HTML中,重點只有在「runat="server"」,把HTML轉換為HTML控制項,成為控制項後,ASP.NET才能進行程式碼的操作。

使用Calendar控制項+jQuery實作DatePicker

我們在讓使用者輸入資料時,常有機會需要讓使用者選擇日期,所以而這種選擇日期的功能我們稱「Date Picker」,你上網搜尋,可以找到一大堆資源,但我想要使用ASP.NET裡的Calendar加jQuery來實作看看,動手做,樂趣無窮。

做法很簡單,我們先新增一default.aspx網頁,然後在網頁上放上一個TextBox及一個<img>,TextBox是讓使用者選擇完日期後,把日期放入TextBox之中,而<img>是顯示及隱藏Calendar控制項。

Default.aspx

<form id="form1" runat="server">
<div>
<asp:label associatedcontrolid="tbxDate" id="lblBirthday" runat="server" text="生日:">
        <asp:textbox id="tbxDate" runat="server">
        <img alt="選擇日期" id="ibnt" src="Calendar.png" />
</div>
<asp:calendar backcolor="White" bordercolor="#999999" cellpadding="4" daynameformat="Shortest" font-names="Verdana" font-size="8pt" forecolor="Black" height="180px" id="cal" runat="server" width="200px">
            <selecteddaystyle backcolor="#666666" font-bold="True" forecolor="White">
            <selectorstyle backcolor="#CCCCCC">
            <weekenddaystyle backcolor="#FFFFCC">
            <todaydaystyle backcolor="#CCCCCC" forecolor="Black">
            <othermonthdaystyle forecolor="#808080">
            <nextprevstyle verticalalign="Bottom">
            <dayheaderstyle backcolor="#CCCCCC" font-bold="True" font-size="7pt">
            <titlestyle backcolor="#999999" bordercolor="Black" font-bold="True">  </titlestyle></dayheaderstyle></nextprevstyle></othermonthdaystyle></todaydaystyle></weekenddaystyle></selectorstyle></selecteddaystyle></asp:calendar>
</form>

我們先在Defuault.asp.vb中處理ASP.NET的相關事件。

Defuault.asp.vb

  Protected Sub cal_DayRender(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DayRenderEventArgs) Handles cal.DayRender
        '生日不會大於今天,所以把大於今天的日期選取功能取消
        If e.Day.Date > DateTime.Now Then
            e.Day.IsSelectable = False
        End If
    End Sub

    Protected Sub cal_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cal.SelectionChanged
        Me.tbxDate.Text = Me.cal.SelectedDate.ToShortDateString
    End Sub

最後就是處理Calendar顯示及隱藏的jQuery:

jQuery - position

$(function() {
    //先隱藏Calendar
    $("#cal").hide();
    //<img>的click事件
    $("#ibnt").click(function() {
        var p = $("#ibnt");
        //可使用position或offset來取得<img>的top及left座標
        //var position = p.position();
        //$("#cal").css({ "position": "relative", "top": position.top, "left": position.left });
        var offset = p.offset();
        //設定相對位置
        $("#cal").css({ "position": "relative", "top": offset.top, "left": offset.left });
        $("#cal").toggle();
    });

    //讓TextBox也能有<img>一樣的效果
    $("#tbxDate").click(function() {
        var p = $("#tbxDate");
        var position = p.position();
        $("#cal").css({ "position": "relative", "top": position.top, "left": position.left });
        //var offset = p.offset();
        //$("#cal").css({ "position": "relative", "top": offset.top, "left": offset.left });
        $("#cal").toggle();
    });
 });

簡單吧,不過由於我們是使用ASP.NET的Calendar控制項,所以在點選時,會產生Postback,才有辦法把值寫入TextBox中,不像一般純JavaScript那樣單純,把值直接寫入TextBox中。控制項有控制項的好處,或許我們還能用CallBack來改寫,或使用Ajax實作來減少Postback,但我的重點是在jQuery,簡單又實用。

當業績與良心對上時

我的Focus已經過保固有一段時間了,因為習慣,雖然有認識保養廠的朋友,但我還是都回原廠保養。但近來我的Focus出現冷車異音的問題,但發生的頻率還不到100%,所以每次回原廠保養也沒查出什麼所以然?要嘛就不出聲,要嘛就咻咻咻的叫。

但這都不是問題,一般的保養是沒有什麼問題,但最近幾次進廠,都會有意外出現,我所謂的意外就是會發生:「先生,我們保養的過程發現你的愛車xxx有問題,這可能會有安全性上的問題,請問你是否要做更換?」

通常我們又不懂這些專有名詞,懂的只是皮毛,又聽到「安全性」上的問題,通常都會花錢了事,不過幾次下來,總覺得不對,而且每次都是壞那種我認為很奇怪的地方,例如有一次,Ford跟我說我Focus有一隻避振器漏油,問我是否要更換?我心想,我的Focus大多只跑高速公路,我們台灣的高速公路能「振」到Focus避振器漏油,也太不容易了吧,原本我是不想換,但剛好假日又要回宜蘭,心想,又是長途、又是安全性問題,而且重點是,我現在車上有寶寶,花錢了事吧。

重要的是,Ford每次這種「換東西的問題」產生時,你要換也可以,不換也可以,不換的話Ford是不會也不會跟你說什麼,好像出事也不關他們的事一樣,這樣的態度讓我有了疑心。照理說,如果真的會影響到安全(因為可能會死人),說什麼也要跟顧客解譯清楚,就算不在原廠維修,也要提醒顧客這個問題一定要去處理好,不要去影響到行車安全。

所以這一次送去保養後,真的電話又來了,又說我xxx有問題,是否要更換零件。這一次我就直接說不用了。我將車開回來了直接去找我保養廠的朋友,請他幫我看原廠說的那個問題,第二天我朋友打電話來,說原廠在放屁,他們要做業績,你不用理他們。

我說,做業績是什麼意思?我朋友說,你的零件根本沒問題。朋友還說,他學弟就在Ford原廠,他學弟跟他說,Ford原廠會要求業績,一台車進廠,沒花到5000以上他們會被「釘」,而且每個月還有60萬的業績要求,所以像我們這些過保的車,就是他們下手的目標。反正我們什麼也不懂,隨便唬唬可以達到要求了。

我朋友的解譯跟我的想法match,這樣的說法,請各位去求證,我也只是聽說,但我是相信的那一個。如果有問題,還是到現場請師博說明給你看,他們知道你是會到現場看的人,或許比較不敢這用電話唬人。

即時先行編譯(in-place precompilation)

我們都知道,在ASP.NET中,第一次被瀏覽的網頁會比較慢才會做出反應,原因是第一次被瀏覽的網頁需要complier,第二次就不用再complier,但如果我們想一開始就把全部的網頁都complier好,那可以使用即時先行編譯(in-place precomplation)技術。

如果網站剛上線,或Server維護重開機,可以使用這個方便的小工具,幫我們先把全部的網頁「點一遍」,也因為每一頁都被點過了,也代表每一頁都被complier過了,所以第一位進來的仁兄,不用等那麼久。

通常使用下面範例二即可。

C:\Windows\Microsoft.NET\Framework\v2.0.50727>aspnet_compiler.exe /?

先行編譯 ASP.NET 應用程式的公用程式
Copyright (C) Microsoft Corporation. All rights reserved.

使用方式:
aspnet_compiler [-?] [-m metabasePath | -v virtualPath [-p physicalDir]]
                [[-u] [-f] [-d] [-fixednames] targetDir] [-c]
                [[-keyfile file | -keycontainer container]
                     [-aptca] [-delaySign]]
                [-errorstack]

-?            列印這段說明文字。
-m            應用程式的完整 IIS Metabase 路徑。這個參數不能和 -v 或 -p 參數結合。
-v            要編譯的應用程式的虛擬路徑 (例如 "/MyApp")。如果已指定 -p,就會使用實體路徑尋找應用程式,否則會使用 IIS Me
tabase,並假設應用程式位於預設網站 (在
              "/LM/W3SVC/1/Root" 下)。這個參數不能和 -m 參數結合。
-p            要編譯的應用程式的實體路徑。如果遺漏 -p,就會使用 IIS Metabase 尋找應用程式。這個參數必須和 -v 結合。
-u            如果已指定這個路徑,就可以更新先行編譯的應用程式。
-f            如果目標目錄已存在則覆寫。現有的內容將遺失。
-d            如果已指定,會在編譯時發出偵錯資訊。
targetDir     編譯應用程式的實體路徑。如果未指定這個路徑,則會就地先行編譯應用程式。
-c            如果已指定,先行編譯的應用程式便會完整重建。任何之前編譯過的元件都會重新編譯。已指定 targetDir 時,永遠啟
用此選項。
-keyfile      強式名稱金鑰檔的實體路徑。
-keycontainer 指定強式名稱金鑰容器。
-aptca        如果已指定,強式名稱的組件將會允許部分信任的呼叫端。
-delaysign    如果已指定,建立時組件不會完整簽署。
-fixednames   如果已指定,編譯的組件將會獲得固定的名稱。
-nologo       隱藏編譯器著作權訊息。
-errorstack   顯示可協助進行特定條件偵錯的額外偵錯資訊。

範例:

下列兩個命令功能相同,而且都倚賴 IIS Metabase。編譯完成的應用程式會部署到 c:\MyTarget:

    aspnet_compiler -m /LM/W3SVC/1/Root/MyApp c:\MyTarget
    aspnet_compiler -v /MyApp c:\MyTarget



下列命令會就地編譯應用程式 /MyApp。如此一來,當 HTTP 要求傳送至這個應用程式時,就不再需要進行編譯:

    aspnet_compiler -v /MyApp



下列命令「不」倚賴 IIS Metabase,因為它會明確指定應用程式的實體來源目錄:

    aspnet_compiler -v /MyApp -p c:\myapp c:\MyTarget

ASP.NET多國語言開發快速體驗

在ASP.NET之中,如果要開發多國語言的網頁,已經比其他程式語言簡單許多。而我們在開發多國語言時,都會使用組件資源檔(*.resx),加到「\App_GlobalResources」資料夾中,資源檔的內容是字串構成的對照表格,而且除了字串,也能將圖檔或其他檔案加入資源檔之中。

我們先在\App_GlobalResources中新增一個資源檔

Resource.resx

名稱:PageTitle
值:English Sample Page

再新增一個繁體中文資源檔

Resource.zh-TW.resx

名稱:PageTitle
值:繁體中文抬頭網頁


新增Default.aspx網頁,在@Page指示詞最後加上「Culture="Auto" UICulture="Auto"」兩屬性,跟ASP.NET說,此網頁請自動幫忙選擇文化屬性。

最後我們在Page_Load新增以下程式碼:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   '由資源檔Resource讀取PageTitle的值
   Page.Title = Resources.Resource.PageTitle
End Sub

要取得資源檔裡名稱與值很簡單,使用Resources.資源檔.名稱就可以取得名稱的值。這樣我們馬上就完成一個自動判定語系的網頁,而且會自動抓取抬頭設定值,如果你是使用繁體中文的瀏覽器,那網頁的抬頭應該是「繁體中文抬頭網頁」,其他語系瀏覽器應該都是「English Sample Page」。ASP.NET會自動判定你的語系,抓取對應的資源檔,如果沒有對應的資源檔,會使用預設資源檔的值(Resource.resx)

在設計上,我們會先計設一個預設語言的資源檔,再依序新增其他語言的資源檔,例如:
WebResource.resx (預設)
WebResource.zh-TW.resx
WebResource.zh-CN.resx

這裡有一點要注意,就是後面新增資源檔的「語系」命名不能隨便亂設,例如你把繁體中文的資源檔命名為WebSource.Big5.resx、WebSource.GB2312.resx,而是要依照.NET Framework中CultureInfo類別的規定來命名。

另外,如果你只想讓某一個.aspx網頁使用資源檔,則需要將資源檔新增至「\App_LocalResources」資料夾之下,然後依網頁名稱來命名資源檔名稱及相關資源檔。

例如,我有一個讓User下載資料的網頁Download.aspx,所以我們在\App_LocalResources新增以下資源檔:
Download.aspx.resx
Download.aspx.zh-TW.resx
Download.aspx.zh-CN.resx

這樣明白了吧,就把是直接用網頁名稱來命名資料檔,然後再依照預設資源檔來新增相關語系(zh-TW、zh-CN…)的資源檔,當ASP.NET執行到Downloads.aspx時,會自動去判斷瀏覽器的語系,再去找相對應的資源檔,再顯示出相關語言的頁面。

記得,語系(zh-TW…)的命名一樣是要照規定。

全球一動WiMAX(4G)初體驗,新竹測試募集

http://event.g1.com.tw/cb/

細節請入內自行觀看,明天(10/30)是最後一天,想要的人手腳要快。

SQL語法之Insert-Update-Delete三部曲

如果你常下SQL語法,久了就會了解,不外呼兩大部份,一是Select,一是異動,含Insert-Update-Delete,雖然標題是三部曲,但今天主要是介紹Insert及Update這兩個使用上的一點小技巧。

Insert語法


標準語法:
Insert into orders values ('2009/10/29', 1010, NULL)

Insert into orders(order_num, cust_num, order_date) values (200, 1010, '2009/10/29')

以上兩種是標準Insert的用法,而且我們在寫網頁時,常常要「組合」這種語法,欄位一多,跟看3D立體圖差不多,常常為了對應欄位與值,少一個「'」符號,在那裡Debug。

但在Insert語法中還可以使用execute statement,通常我們使用Select可以從資料表中取回資料,但資料可能是一筆,可能是十筆、百筆、萬筆等大量資料,也可能什麼都沒有,但我們可以搭配Insert語法,將Select取回的資料全部Insert進指定的資料表中,來簡省大量輸入及除錯的時間,想想用手輸入1000筆和執行兩三行指令,你要選那一個。

進階語法

Insert into [kk].[dbo].[orders] (order_num, order_date, customerid)
Select order_num, order_date, cust_num from orders

將原本Insert後面values的語法修改為Select語法,而且這個語法的好處可以把原本在Insert語法的重心,重新拉回來Select的身上,只要將規則或條件(Where…)設好,就可能取回你想要的資料,又不用怕輸入錯誤,真的是一舉二得。

Update語法

標準語法:
Update products set phone='035678901' where cust_num=1010

Update product set unit_price=unit_price * 1.05

以上兩種也是常見的Update使用方法,但Update還有一種用法是修改的來源是從某張資料表內的資料,像是Insert可以從別的資料表取得資料一般。

進階語法

update items set unit_price=products.unit_price
from products
where items.prod_num=products.prod_num and items.supp_code=products.supp_code and order_num>888

第一行,我們將products中的價格指定給items;
第二行,指定來源資料表;
第三行,Where條件,確認products中PK;

以上紹介的這兩種進階語法,都是一般入門書中比較不易看到的,提供出來給大家參考。

小巧(108KB)好用的SQL指令執行工具--QueryExpress

你是否想過,SSMS是非常強大的SQL Server管理工具,但安裝檔又大,安裝步驟又麻煩,又是.NET Framework,又是powershell,installer還要4.5以上…如果只是為了下幾行的Select * From Customer,就要安裝SSMS,實在划不來。

今天介紹一個工具「Query Express」,其實這個工具已經出來很久了,但實在好用,而且作者還提供原始程式碼,程式complier出來後,了不起108KB,透過這個工具,加上SQL語法,你已經可以完成資料庫裡應該80%以上的工作沒有問題,而且我測試SQL Server 2005/2008 (Express)都可以正常使用。

再更簡單的說,你也只能透過Query Express來向SQL Server執行SQL語法或T-SQL,只要SQL Server能接受的指令,通通可以透過Query Express來執行。

User → QueryExpress(T-SQL) → SQL Server

因為使用上太簡單了,我就不多介紹,因為重點是在SQL語法T-SQL身上,而不是軟體,軟體只是中介。另外作者有提供原始程式碼,所以我就手癢癢,使用VS2008重新complier及正(繁)體中文化了一下。而且Query Express本身是綠色免安裝軟體,你可以放在隨身碟裡,想用就用,實在太得我心了。

補充:從原作者網站還可以發現另一個好用的linqpad,這有空再介紹。

ps:原始程式是使用vs.net 2003寫的,程式部份是使用C#。
ps:原始網頁:http://www.albahari.com/queryexpress.aspx

Query Express繁體中文版:

$1,688 免費 AdWords 關鍵字廣告試用

有需要的人拿去吧,但請回覆你已使用了。

$1,688 免費 AdWords 關鍵字廣告試用,讓您立刻上網招攬客戶

親愛的 Google Analytics 用戶
較早前我們送您的 $1,688 Google AdWords 關鍵字廣告試用券,必須在 10 月 30 日前申請,逾期無效!現在,請立即前往 Google AdWords 網頁登記!
Google AdWords 的五大優點
  • 傳播範圍最大: Google 的內容聯播網涵蓋73%* 亞太區網路使用者,並是全球最大的廣告平台
  • 廣告有效,才須付費: 廣告刊登是免費的,有人點擊廣告,您才須付費
  • 有效控制廣告預算: 無預算門檻限制,且隨時可依需求調整每日預算
  • 廣告最彈性: 隨著您的促銷活動或新產品上市,隨時設計新廣告或調整廣告投放地區及網站等設定
  • 設定最快速: 15分鐘就能建立廣告並開始播放
如何兌現 AdWords 關鍵字廣告試用券及連結您的 Analytics 帳戶:
1. 前往 http://adwords.google.com.tw 首頁,按「立即開始」建立您的帳戶。
2. 進入您登記的電子信箱收帳戶啟用信,登入 AdWords,依照指示逐步設定廣告活動、群組及廣告和關鍵字。
3. 請在「帳單」-->「帳單偏好設定」填寫完整資訊以啟動帳戶。
4. 並請在「兌現促銷的相應號碼」一欄內,輸入您的試用券折換代碼-AXU9-2VUC-6F2T-KMG5-C8N
5. 按「儲存並啟用」後,您的廣告過不久就會上線!
要結合您的 Analytics 及 AdWords 帳戶,請依照這裡的 指示設定。結合 Analytics 及 AdWords,將能幫助您明確監測廣告效果,及瞭解如何持續優化您的關鍵字廣告。
需要協助嗎?請於週一到週五9:00到17:30間致電免費新客戶服務專線 0800-777-799,Google 將有專人協助您建立帳戶。
Google 台灣 Analytics 小組
P.S. 現在就申請使用 Google AdWords,幾個步驟就能取得$1,688元免費關鍵字廣告費。請注意此優惠方案僅限新客戶。折換代碼須於2009年10月30日前使用。

使用條款
這個優惠必須在新 AdWords 帳戶啟動後14日內使用,並必須為自行操作帳戶的線上廣告客戶,其他管道的客戶並不適用。如果您的廣告費用超過試用券贈送的金額,我們會向您收取超出的費用;若不願付出額外費用,客戶需在贈送金額用畢後停止廣告活動。廣告客戶必須擁有有效的 AdWords 網上廣告帳戶,同意廣告通過 Google審核,並接受 Google AdWords Program 條款。若此優惠方案違反法律,則優惠方案無效。試用券金額不得供轉贈、出售或交換。Google Taiwan Limited 保持更改或取消這個活動的最終權利。每一個試用券代碼只供一位客戶使用。廣告客戶須繳付新台幣200元開戶費,但我們提供的試用券已多出200元以抵銷您支付的開戶費。選擇預付方式的客戶,必須先繳付新台幣400元,其中200元為開戶費,200元為可使用的廣告費。有效日期截至:2009年10月30日。
*comScore Media Matrix, July 2008
© 2009 Google Inc. 版權所有。Google 及 Google 商標為 Google Inc. 的註冊商標,
1600 Amphitheatre Parkway, Mountain View, CA 94043.

電郵設定:我們寄這個電郵給你,由於你曾表示願意收到 Google Analytics 及其他 Google 產品的資訊。如果不想再收到這些推廣郵件,請前往您的 Google Analytics 帳戶修改設定版面 (https://www.google.com/analytics/settings/my_account - 需要使用Google Analytics 帳戶登入),取消勾選「特別推廣」(Special Offers)的方格並儲存。

網頁式FTP Client

FTP Client,是要翻譯成「用戶」、「用戶端」、「用戶端連線軟體」,不知那個比較好?

相對於FTP Server,FTP Client也就是跟Server連線的軟體,透過FTP Client與FTP Server連線後,只要權限足夠,那我們可以管理FTP Server上的檔案,上傳、下載、新增、刪除,這不管是在我們檔案管理、網站網頁管理,FTP Server/Client絕對有很大的功勞。

但對於使用者而言,最常用也最常出現「莫名奇妙」問題的FTP Client就是IE,而我們又不能要求這些一般使用者安裝較好的FTP Client軟體,如FileZilla…,這個是我長久以來的問題點,不想讓使用者使用IE來連接FTP Server,尤其是上傳等動作。

所以我找到一個網頁FTP Client的網站,它提供網頁式FTP Client的功能,讓我們可以透過它來登入FTP Server,然後做想做的事。

net2ftp

使用上直覺又簡單,而且還提供多國語系,我透過net2ftp來連台灣及大陸的FTP,速度上都還可以接受,反應時間約在3-4秒。而它除速度不是咻咻咻等級,大概只有帶一點廣告,是我比較不喜歡,其它都是可接受。

而且它還提供原始檔,讓大家可以下載使用,哦,真是佛心級的啦!

SQL Server 2008 Express壓縮功能

原來規格是「參考用」。

之前在寫SQL Server 2008 Express文章時,有放一個「SQL Server版本差異」連結,其中第一項中有一個項目是「資料壓縮」,你會發現,除了Enterprise版本,其他版本都不支援。

在操作SSMS管理工具時,也常被類似「此版本無法執行xxx功能」等訊息爆眼睛,造成眼睛的不適@.@,所以規格上沒有列的東西,也就不想去玩。

不過,今天又學到一個心得,只要管理工具出現可以「玩」的,不要客氣,只要不會讓你的資料庫掛了,讓你的資料毀了,一點訊息,還能接受。

在SSMS工具 &rrar; 選擇資料庫 &rrar; 工作 &rrar; 壓縮 &rrar; 資料庫/檔案

請不要客氣,在SQL Server 2008 Express真的可以透過SSMS手動壓縮資料庫或資料庫檔案,我想,那規格上的壓縮是指動態、全自動的壓縮。

想到可以壓縮資料庫,心情就很好!

ASP.NET網站管理工具的Table新增至自己的資料庫

在ASP.NET 2.0裡提供了好用又強大的會員管理控制項,而且只要在Visual Studio中點擊「ASP.NET組態」就可以馬上使用「ASP.NET網站管理工具」,但預設會在「~/App_Data」之下產生一個「ASPNETDB.MDF」的資料庫檔案,內建了11個系統預設資料表。

如果今天我們想把這些資料表整合到我們自己的資料庫中,那要怎麼做?其實一點都不難,方法有二(其實都是同一個方法,一個使用GUI,一個使用指令):

一、使用GUI(使用檔案總管)
1. 先切換目錄到
C:\Windows\Microsoft.NET\Framework\v2.0.50727
二、點擊ASPNET_REGSQL.EXE;
三、依畫面輸入「主機名稱、帳號、密碼、資料庫名稱」;

主機名稱可以是本機也可以是遠端,只要你的帳號有足夠的權限,都可以新增資料表,按下確定後,系統就會自動將11個表格新增至你所指定的SQL Server的資料庫中。

二、使用指令(cmd.exe)

1. 先切換目錄到
cd C:\Windows\Microsoft.NET\Framework\v2.0.50727
2. ASPNET_REGSQL.EXE指令
aspnet_regsql.exe -S papa -U kkbruce -P 1029384756 -d KKDataCenter -A all
按下Enter,一樣,系統會自動新增資料表到指定的資料庫中。
3. 訊息




開始加入下列功能:
Membership
Profile
RoleManager
Personalization
SqlWebEventProvider

.....

已經完成。




-S:SQL Server資料庫主機名稱。
-U:帳號。
-P:密碼。
-d:資料庫名稱。
-A:加入哪些Provider支援,all指全部要支援。

C:系統磁碟空間不足怎麼辦?

如題?

在一台運行近五年的Server上,近來一直跳出「系統磁碟空間不足」的可怕訊息,一看,事情還很大條:



一開始只能簡單的「清一清」,但效果不佳,沒幾天就又跳出一樣的訊息,有什麼好辦法呢?而且重點在「系統磁碟」,又沒辦法清除再重做,重新Format就沒事了?Server重灌嗎?這是不可能的。

我想到一個好辦法:



不要不相信,就是那麼簡單,一個勾勾,解決所有問題;在壓縮的過程,會要幾個小時之久,然後:



從150MB變成14GB,這可不能說不補,但要犧牲一丁丁點效能,因為作業系統會把所有用不到的檔案程式全部壓縮,在你要使用時再進行解壓縮等動作,所以中間會有一點點效能的差異,但拿效能換來的空間,我覺得太值得了。

SQL Server 2008匯入資料

我需要台灣郵政資料,所以上去中華郵政,現在中華郵政很不錯,有提供電子檔或軟體給大家下載使用,而我需要在資料庫建台灣郵政資料,而中華郵政有提供3碼與5碼郵政資料電子檔,所以就下載回來。

中華郵政下載頁

原先我很呆,因為以前的SQL Server Express版本,記得是沒有匯入功能,想要使用匯入功能,那可是要花$.$,而我也沒想那怎多,處理的方法有二,一是寫段程式,將Excel檔的資料轉存到SQL Server中,二是,建好資料表及資料欄位,然後用「Copy & Paste」的古老方法,因為想快點完成功工作,所以我選擇了方法二。

結果,沒用沒事,用了看起來是最快的方法,結果速度奇慢無比,在從Excel copy to SQL Server過程裡,SSMS完全無法動作,而且Paste速度奇慢,只能看到畫面下面新增成功的資料數一筆一筆慢慢的增加,但Excel中有58865筆資料,Paste一次約要40分鐘以上,天呀~是給我時間泡Coffee,看報紙嗎?

不行。

找了找,試了試,答案原來那麼簡單。先說答案,再來看操作。答案就是,SQL Server 2008 Express支援匯出、匯入功能。原本搞了一下午的工作,在短短的數十秒內被秒殺~秒殺~秒殺~秒殺~秒殺~秒殺~秒殺~秒殺(看了好爽,再多看幾次)。

這次的經驗也讓我學到,以前沒有不代表現在沒有,以前有的也不代表現在會有。把每一次當成全新的開始,好好的學習。

接下來我們看看操作。

我們把台灣郵政資料匯入範例資料庫Northwind:

1. 先下載台灣郵政資料(3碼、5碼隨便),解出Excel(*.xls)檔案;
2. 在SSMSE → Northwind → 右鍵 → 工作;



我們選擇「匯入資料」→ 出現「匯入和匯出精靈」;



在「選擇資料來源」頁面:

資料來源:目前有17種資料來源可以選擇,常用的Access / Excel都有支援,看了好高興,資料來源下方面設定選項會依你選擇不同的資料來源有所不同。我們選Excel。




Excel連接設定:

Excel檔案路徑:選擇Excel所在路徑。
Excel版本:系統會自動偵測。
第一個資料列有資料行名稱。(依情況自行勾選,我們的實例中是不能勾選)



選擇目的地及設定驗證方式:




目的地不一定是SQL Server,也就是說,你可以使用SSMS工具來做資料轉匯的工作,我之前都是使用Access在做這方面的工作。(但我未測試)

指定資料表複製或查詢



我們可以選擇從資料表來匯入,或是寫SQL語法過濾後來匯入;

選擇來源資料表和檢視


選擇要預覽的資料表,然後按下預覽鈕;



執行封裝:也就是執行匯入工作;



成功執行訊息;



這就我們就完成了Excel to SQL Server資料匯入的工作。

真的是「快又有效」。

但有一點要注意,就是匯入的資料格式都是採預設值,如欄位的資料型態都是nvarchar(255),還有欄位名稱是F1, F2, F3, F4,這些事後要記得修改。

順便看一下台灣郵政資料的Schema:

TaiwanPost(<ZipCode,nchar(5)>,<City,nchar(3)>,<Area,nchar(3)>,<Road,nvarchar(11)>,<Scoop,nvarchar(23)>)

微軟詞彙入口網站

微軟詞彙入口網站:http://www.microsoft.com/language/zh/tw/default.mspx

真是相見恨晚的感覺,這個網站把所有Microsoft所使用的詞彙統一整理起來,然後你可以使用它來比較各個詞彙在不同語言裡的翻譯或使用的不同。

例如:

英文詞彙:object
語言:選「中文(台灣)」
結果:物件
(還有其他很多資料...)

英文詞彙:object
語言:選「中文(中華人民共和國)」
結果:对象

一開始的頁面只能「英文-->其他」,但等進到查詢完成頁面,就能「其他-->英文」。

例如:

原文:巡覽
語言:中文(台灣)
譯文:英文
結果:

Nav 巡覽 Visual Studio
Nav 巡覽 .NET Framework
Pager&#0; 頁面巡覽區 .NET Framework
Pager&#0; 頁面巡覽區 Visual Studio
Navigate 巡覽 Visual Studio
Navigate 巡覽 .NET Framework
Navigable 可巡覽 Visio
Navigation 巡覽 Visual Studio
Navigation 巡覽 Unkown
Navigation 巡覽 Access

如果你在msdn或technet或其他關於微軟技術文件上有看不懂的地方,建議可以先上這個網站查查相對應的翻譯。

CSS margin值的設定

CSS margin


margin : 0;
/*一個值:代表上、下、左、右。margin : 0 0 0 0;的簡寫。*/
margin : 5 10;
/*二個值:值1:上下、值2:左右。margin : 5 10 5 10;的簡寫。*/
margin : 5 10 15;
/*三個值:值1:上、值2:左右、值3:下。margin : 5 10 15 10;的簡寫。*/
margin: 1 10 5 15;
/*四個值:值1:上、值2:右、值3:下、值4:左。*/

margin auto


margin裡的auto通常是拿來「置中對齊」使用。也就是我們將左右邊界值設定為「auto」,讓它產生置中對齊的效果。

/*方法一*/
margin-left : auto;
margin-right: auto;
/*方法二*/
margin : auto;
/*方法三*/
margin : 上下 auto;
margin : 0 auto;
/*方法四*/
margin : 上 auto 下;
margin : 0 auto 0;

簡易Menu導覽(巡覽)列加文章下拉效果

我要來實作一個簡單的Menu導覽(巡覽)列。

一、先首我們準備好HTML內容:


<!--巡覽列-->
    <div id="navigation">
        <div id="container">
            <ul id="firstul">
                <li id="home" class="active"><a href="#" title="Home">首頁</a></li>
                <li id="news"><a href="#" title="讀書心得" id="mynews">讀書心得</a></li>
                <li id="about"><a href="#" title="有關我" id="about_us">有關我</a></li>
            </ul>
            <div id="mypage" style="display: none" align="center">
            </div>
        </div>
    </div>
    <!-- 文章:預設只顯示標題 -->
    <div id="content">
        <span id="title01">數位式競爭--讀書心得</span><br>
        <div id="title01_content" style="display: none;">
            這本書為民國89年出版,已經在我書架上很多了年,是我讀大學時的教科書,老師花了一個學期就只上這本書,當時讀起來沒什麼感覺,頂多只是為了交報告而讀,但很奇怪,它就是一直在我的書架上,雖然十多年來,書架上的書已經換了好幾回,尤其是資訊類的書,換的速度之快連我都怕,不過一本好書一定有存在的價值,不會因為時間的變動而有任何改變。我每天可以說都在與技術文件為「舞」,只是不知是我看它跳還是它看我跳。就這樣有一天,不知為何,好像「它」在跟我招手,然後說,來看看我吧,離上次你讀我已經是九年多前的事了,我能給你一些「明牌」!古人說:「不經一事,不長一知。」你沒有經歷過的事,說再多感受就是有限。但九年後的今天重讀本書,真是感受良多,這本書應該是十年前版的「由A到A+」。我一直很佩服國外的研究學者,能花那麼多時間、精神來研究出原本為「隱性」的知識,讓想要更上一層樓的人可以有方法可循。看完這本書後,讓我心有戚戚,十多年前的故事,現在每天還是在不斷重覆發生,不管是成功的故事,還是失敗的故事。我想這可能是知識的傳遞、了解到最後的落實還有很大一段差距。如果你從事軟體相關產業,而還沒有看過這本書,我非常建議你買來看看(我不知道還買不買的到)。
        </div>
        <span id="title02">The Last Lecture -- 讀書心得</span><br>
        <div id="title02_content" style="display: none;">
            「最後的演講」,是一位父親留給孩子的遺言。沒錯,是遺言。聽起來是個不好的消息,但也因為是遺言,所以他必須認真思考要留下什麼給他的孩子們,他晚婚,他小孩都還小,他有成就,他患癌。最後的演講分為兩個部分,一是演講影片,二是書本。我是先看書再看影片,影片的部份,你可以搜尋「朱學恆」在他的部落格裡有影片檔和中文字幕,影片是免費的。這場演講為什麼會是全世界轟動?我想,除了是作者蘭迪.鮑許(Randy
            Pausch)本身在面對癌症時還能散發不可思義的"樂觀"魅力,還有一種「人之將死,其言也善。」的人生智慧在裡面。人生有方向,是多麼重要及快樂的一件事,首先,是完成自我的夢想,然後是啟發他人的夢想,還可以進一步幫助他人完成夢想。這是Randy教授最後想跟我們說的話。反之,也就是人生一定要有「目標」、要有「方向」,要知道你自己的「路」在那裡。這或許是我喜歡讀些哲學類的書籍關係,思考一件的事的角度之多,或許不是你能想像的,提高看事的高度,提高做事的層度,努力的成就自己,但也不要忘了幫助別人,造成一個良性循環的社會。
        </div>
        <span id="title03">Word of Mouth Marketing--讀書心得</span><br>
        <div id="title03_content" style="display: none;">
            我的信箱中有許多的電子報,每天上班第一件事就開打開信箱,確認一下有沒有重要人士的信件,看看Log信件,看看電子報,其實訂了那怎多的電子報,絕大部份都在1-10秒內被我的食指結束生命,快快的按下那Delete鍵,然後Next。而某天的一封電子報裡刊載的標題讓我有興趣「掃」一下,看完後(很少有認真看完全部),內容簡潔但又不失內容,後來又收到幾期的內容,一樣,都是很直接也實用的內容,文筆也不會看了想睡覺。這些電子報其實也是行銷手腕的一種,精選幾段精彩的內容,吸引你的注意,如果你也確實被吸引,但因為你只是看到部份的片面,這時就要看這些精彩的內容是否有足夠的吸引內,讓你採取行動,拿出新台幣去換一本有完整內容的書本。而我,被打動了。雖然我不是行銷人員,但我對行銷、管理方面的知識算很有興趣,一樣是動腦的工作,但行銷、管理和程式就是不同。而作者除了提供大量免費實用的做法外,也提供簡單的5個步驟打造好的「口碑」。
        </div>
    </div>


  • 巡覽列:我們先使用ul及li元素配合CSS來做UI的工作。
  • 文章:一開始只會顯示標題,使用者點選標題,才顯示文章內容。

二、巡覽列之CSS


/*ul元素設定*/
#navigation ul
{
 list-style-type : none ;
 margin : 0 auto; /*置中*/
 padding : 0;
 width : 850px;
}

/*讓li"浮"起來,變成"橫向列"*/
#navigation li 
{
 float : left ;
}

/*Menu中a元素設定*/
#navigation a 
{
 float : left ;
 display : block ; /*以「區塊」元素方式顯示*/
 color : rgb(197,197,197);
 padding : 5px 8px;
 margin-top : 10px;
 border-bottom-width : 0;
}

/*li中類別為active的a元素設定*/
#navigation li.active a
{
 color : rgb(255,204,0);
 background-color : rgb(153,153,153);
}

/*Menu中a元素:hover及:active設定 */
#navigation a:hover, #navigation a:active
{
 color : rgb(204,204,255);
 background-color : rgb(100,90,125);
}

/*文章區塊,<div id="content">設定 */
#content
{
 clear : both ;
 width : 850px;
 margin : 0 auto; /*置中*/
 padding : 0;
 background-color : rgb(193,189,204);
}

/* 文章標題,讓jQuery動態加入 */
.newstitle
{
 color :Black ;
 border-bottom : 1px dotted gray;
}

/* 文章內容,由jQuery動態控制  */
.newscontent
{
 width : 50%;
 color : Black ;
 background-color : rgb(255,153,51);
 border : 1px dotted gray;
 padding : 7px 30px 10px 25px;
}

建議一段一段複製,看整個畫面變化的過程,才能了解為什麼這樣設定。

三、jQuery程式碼


再來就是jQuery來設定文章標題樣式及文章內容顯示部份:
$(function() {
    $("#firstul li:eq(0)").removeClass("active"); //先將"首頁"的類別移除
    $("#firstul li:eq(1)").addClass("active");  // 將"讀書心得"設定.active類別
    $("span[id]").addClass("newstitle"); // 文章標題設定

    $("#title01").click(function() { //點擊標題時,
        //文章內容加入.newscontent類別設定
        $("#title01_content").addClass("newscontent").toggle("slow"); 
        //其他非title01的內容,全部hide()
        $("div[id^=title]:not(#title01_content)").hide("slow");
    });

    $("#title02").click(function() {
    $("#title02_content").addClass("newscontent").toggle("slow");
    $("div[id^=title]:not(#title02_content)").hide("slow");
    });

    $("#title03").click(function() {
    $("#title03_content").addClass("newscontent").toggle("slow");
    $("div[id^=title]:not(#title03_content)").hide("slow");
    });
});

這樣我們就完成了一個起簡單版的Menu巡覽列(CSS實作)加上切換文章內容功能(jQuery)的網頁。程式還有很多改進的空間,加油!

得知使用者按下按鍵代表的意思

HTML

<div id="myform">
Name:<input />
Email:<input />
</div>

jQuery(1)

$(document).keydown(function(e){
  //keyCode為ESC
  if (e.keyCode == 27) {
  $("#myform").hide("slow");
  }
});

我們透過document來為網頁注冊一個keydown事件,如果使用者focus在網頁上,然後由鍵盤有按下任何一個「鍵」,就可以由e.keyCode來得到一個數字,然後依這個數字,我們就可以寫對應的Code。

keyCode請參考:http://unixpapa.com/js/key.html

另外,我也能使用JavaScript中String物件的fromCharCode方法來得到文字內容,而不是數字。

JavaScript

function keyText(e) {
            // e.which 取得keyCode的數字
            // String.fromCharCode將keyCode轉換成對應的文字
            if (window.event) // IE
            {
                keynum = e.keyCode
            }
            else if (e.which) // Netscape/Firefox/Opera
            {
                keynum = e.which
            }
            alert(String.fromCharCode(keynum) + ":按鍵被按下了");
            return true;
        }

        document.onkeydown = keyText;

但以上JavaScript程式在IE8上會有問題,這也顯示出來一個重點,jQuery在跨Browser上的處理能力比傳統的JavaScript好上許多。如果你是資深的網頁程式開發人員就會知道這種痛,同一支程式,還要先去判斷是IE和非IE,是IE走A,不是IE走B,但有了jQuery可以大大減少這種不必要的幸苦路。

最後,我們再來修改一下jQuery程式,顯示一下我們所按下的按鍵文字(0-9,a-z能正常顯示),記得在IE及Firefox都測試看看。

jQuery(2)

$(document).keydown(function(e) {
  alert(String.fromCharCode(e.keyCode) + ":按鍵被按下了");
  //27為ESC
  if (e.keyCode == 27) {
  $("#myform").hide("slow");
  }
});