December 29, 2013

PictureBox的SizeMode屬性應用

在某個Windows Forms專案中,有個功能是讓使用者點選按鈕後開啟一張圖片在一個表單中。表單使用了PictureBox來載入圖片,其AutoScroll屬性設為True,而PictureBox的SizeMode屬性設為AutoSize。在預設情況下,載入圖片會將PictureBox塞滿整張完整大小的圖片,使用者可以透過scrollbar來瀏覽圖片(如果圖片比表單內容大小還大的話)。


使用者操作過後提出了需求,希望載入的圖片可以適當的比例完整顯示在表單中。要達到這個需求,可以將PictureBox的Dock屬性設為Fill,SizeMode屬性設為StretchImage或Zoom。這個方式會讓PictureBox大小與表單內容大小一樣大,而StretchImage會將載入的圖片塞滿整個PictureBox;Zoom會將載入的圖片以比例顯示在PictureBox。然而這兩種設定對於尺寸較小的圖片,會因此被拉大造成影像失真。

另一個可行的方式是透過程式在載入圖片時做尺寸上的控制。
private void ShowPhotoForm_Load(object sender, EventArgs e)
{
    if (!File.Exists(this._filePath))
    {
        this.DisplayError(string.Format("檔案({0})不存在", this._filePath));
        this.Close();
        return;
    }

    try
    {
        this.PictureBox_Photo.Image = Image.FromFile(this._filePath);
        this.PictureBox_Photo.SizeMode = this.PhotoSmallerThanPictureBox() ? PictureBoxSizeMode.CenterImage : PictureBoxSizeMode.Zoom;
    }
    catch
    {
        this.DisplayError(string.Format("無法開啟檔案({0})", this._filePath));
        this.Close();
        return;
    }
}

[AllowLogging]
private bool PhotoSmallerThanPictureBox()
{
    return this.PictureBox_Photo.Image.Width < this.PictureBox_Photo.Width && this.PictureBox_Photo.Image.Height < this.PictureBox_Photo.Height;
}


PhotoSmallerThanPictureBox方法會回傳載入的圖片尺寸是否小於PictureBox的尺寸。如果是的話,我們將PictureBox的SizeMode設為CenterImage,如此尺寸較小的圖片會被放置在PictureBox正中央顯示。反之,SizeMode設為Zoom,圖片會以比例方式完整顯示在PictureBox內。要注意的是,PictureBox的Dock屬性需設為Fill


November 30, 2013

與Jenkins共舞 - 封存建置成品

在Jenkins成功建置專案後,通常我們會將編譯後的應用程式或軟體封存(archive)起來,作法與備份類似,如此可以方便未來回顧每個建置當時所產出的成品(artifact)為何。例如,每個成功建置的軟體,會有自己的版本編號,將每個不同版本編號的軟體封存起來,除了可以了解目前的建置版本,若釋出的應用程式有defect,也可以取出相對應的版本進行測試。


在Jenkins中若要設定封存功能,可以在Build Job下的Post-build Actions中加入Archive the artifacts


Files to archive中可填入某個路徑或資料夾,如下圖表示要將bin底下所有檔案封存起來。要注意的是,這裡的路徑是相對於Jenkins中workspace的路徑。


設定完成並建置專案,可以在建置成功的結果頁面中看到Build Artifacts樹狀選單,將選單展開即可以看到建置成品。


在檔案系統中也可以看到封存的成品。


如果建置成品是特定副檔名的封裝檔,例如在建置時已經將應用程式封裝成MSI檔,在設定Files to archive路徑時,也可輸入如下圖路徑


Build Artifacts樹狀選單中就可以看到被封存的封裝檔。


到目前為止設定上都不困難,然而Jenkins內建的封存功能,預設是將建置成品各別放在每個建置結果的資料夾下,如C:\Jenkins\jobs\[Job Name]\builds\181\archive\,如此便無法集中管理封存檔。若要集中管理,可以安裝ArtifactDeployer Plugin,也是我目前封存建置成品使用的plugin。設定上不會太困難,有興趣的朋友可以試試。



November 19, 2013

WiX中加入.NET Framework版本檢查 (2)

WiX中加入.NET Framework版本檢查一文中介紹如何在WiX中加入對.NET Framework 4.0的檢查。如果安裝環境沒有.NET Framework 4.0的話,安裝過程中會跳出警告視窗,在使用者按下確定按鈕後即會停止整個安裝過程。


接下來如果使用者想要安裝.NET Framework 4.0,則必須自行瀏覽官方網站進行下載。這時會想,如果能自動開啟官方網站的話對於使用者來說不也挺方便的嗎?透過WiX提供的WixShellExecCustomAction,可在安裝過程中開啟指定網頁,如下
<Property Id="WixShellExecTarget" Value="http://www.microsoft.com/zh-tw/download/details.aspx?id=17718" />
<CustomAction Id="LaunchBrowser" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<InstallUISequence>
    <Custom Action="LaunchBrowser" Before="LaunchConditions">
        <![CDATA[NOT NETFRAMEWORK40FULL]]>
    </Custom>
</InstallUISequence>
<Condition Message="請先安裝Microsoft .NET Framework 4.0再安裝此軟體">
    <![CDATA[NETFRAMEWORK40FULL]]>
</Condition>

屬性WixShellExecTarget裡的Value即為要開啟的網址。InstallUISequence裡則設定了一個CustomAction檢查安裝過程中若系統環境沒有.NET Framework 4.0,則會開啟下載.NET Framework 4.0的官方網站,最後根據Condition發出警告視窗。Condition裡的條件若不成立的話,Windows Installer將會立刻結束安裝。這裡有一點要特別注意的是,CustomAction裡必須是Before="LaunchConditions"而不是After="LaunchConditions"。若設定為After="LaunchConditions",則會因為Condition執行完因條件不成立而停止安裝,網頁將會無法開啟。

參考資料

November 4, 2013

書評 - Clean Code: A Handbook of Agile Software Craftsmanship

圖片來源:天瓏網路書店
在書架上躺了一年多,這兩個月終於花些時間把它看完了。本書為Uncle Bob經典系列作之一,台灣在今年也有中文譯本上市,書名為無瑕的程式碼-敏捷軟體開發技巧守則。這年頭願意翻譯中高階書籍,譯者可謂佛心。本書作者雖掛上Uncle Bob的名字,但部份章節是由其它作者和Uncle Bob的團隊成員所撰寫,書中部份章節及程式碼範例也大多針對Java所寫。針對Java所寫的章節如果興趣不大,可快速瀏覽或跳過,對於閱讀本書其它章節影響不大。本書共有17個章節,四百多頁。

所謂的Clean Code,簡單地說其實就是易讀、可維護、可測試且持續重整的程式碼。

聽起來很簡單做起來卻是不容易。要做到易讀,程式碼的命名就要講究。通常我們寫程式仍以英文為主,對於英文非母語的人來說,英文命名是件頭痛的事,畢竟可使用的字彙有限。事實上,對於英文為母語的人來說也是件頭痛的事。測試?功能都寫不完了怎麼寫測試程式,更遑論重整程式碼了。

要做到Clean Code,牽涉到不只是開發人員的專業度,還有其它許多因素,如時程或政治因素。雖說如此,不代表可以不要做或不能做,所以書中提出的一些看法及作法來達到Clean Code,例如程式碼的命名、註解的寫法及程式碼的排版風格等仍是具有參考性。

身為一個專業的開發人員,寫出Clean Code應該是其畢生所追求的目標之一,至少我是這樣告訴自己。把程式碼寫好,不只是為了日後的維護人員(可能是同事,也可能是自己),也是為了提昇整個團隊產出的品質,降低維護所需的成本。雖然有時出於無奈無法達成,但至少盡力做到便是。對於資深開發人員來說,本書可能有一半的內容已經了解或平常已在實踐,但對於初階開發人員來說本書是相當值得參考。閱讀本書前,如果已經看過以下幾本書,讀起來會更為輕鬆,也較為清楚書中所指意思為何。

Design Patterns: Elements of Reusable Object-Oriented Software
Refactoring: Improving the Design of Existing Code
Agile Software Development, Principles, Patterns, and Practices

以上書籍皆有中譯本。

October 29, 2013

SSMS中清除Server Name歷史紀錄

使用SQL Server Management Studio(SSMS)連線至SQL Server後,SSMS會自動將連線資訊如SQL Server位址、帳號或密碼記錄起來。


但有時我們可能會需要將這些紀錄做清理,例如想將連線名稱重新命名(透過hosts檔案)或是拿掉已經無法連線的主機。在SSMS 2005/2008中不像Oracle SQL Developer有管理連線資訊的功能,個人還蠻希望可以有這個feature,不知為何SQL Server Team沒有將它實作出來。SSMS 2012尚未使用過,不確定這個feature是否有被加入。

在SSMS 2005/2008的折衷的作法則是將C:\Users\Pete\AppData\Roaming\Microsoft\Microsoft SQL Server\100\Tools\Shell\SqlStudio.bin(Pete為登入作業系統的使用者帳號)刪除,server name的連線歷史記錄就會全部被移除,注意是全部,這算是一個小缺點,因為你可能只想移除某個連線資訊,卻要清空所有連線資訊再重新連線其它可用的SQL Server以儲存紀錄。

額外要注意的事,刪除SqlStudio.bin檔案時,SSMS需要關閉,否則SqlStudio.bin即便被刪除,SSMS下次被開啟時SqlStudio.bin還是會回復成舊的歷史紀錄。

September 27, 2013

WiX中加入.NET Framework版本檢查

WiX來打包安裝檔(如*.msi)時,常會希望安裝過程中可以先檢查主機環境是否符合特定需求再進行安裝,例如.NET Framework版本是否能執行欲部署的應用程式,如果不符則顯示警告訊息給應用程式使用者並中止安裝。

在WiX中若要進行.NET Framework版本的檢查,需要借助WiX所提供的延伸函式庫WixNetFxExtension.dll。我的作業系統環境為Windows 7 Professional x64 SP1,安裝的WiX Toolset版本為3.7,預設安裝路徑為C:\Program Files (x86)\WiX Toolset v3.7,延伸函式庫則存放在bin資料夾下。

以下為設定步驟

將WixNetFxExtension.dll加入參考


上圖為SharpDevelop上開啟WiX專案的畫面,目前我是以SharpDevelop來編輯WiX設定檔。


設定檔中根節點Wix中加入命名空間xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension",如
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
  xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension">


Wix/Product/Package節點後加入以下兩個節點,如下為檢查.NET Framework 4.0是否已安裝在系統上,NETFRAMEWORK40FULL代表檢查的是.NET Framework 4.0版本,詳細可使用的版本列表可參考WixNetfxExtension;而Installed則代表檢查是發生在安裝MSI檔時而非修復或移除時。
<PropertyRef Id="NETFRAMEWORK40FULL"/>
<Condition Message="請先安裝Microsoft .NET Framework 4.0再安裝此軟體">
    <![CDATA[Installed OR NETFRAMEWORK40FULL]]>
</Condition>

例如
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension">
 <Product Id="8CB51EE0-0F1C-4185-90BC-11B865F4CFD5" Name="Demo Application" Language="1028" Codepage="950" Version="1.0.0.0" Manufacturer="Pete Chen" UpgradeCode="A887890D-18A1-437A-95D4-0836AC792366">
  <Package InstallerVersion="200" Compressed="yes" Languages="1028" Manufacturer="Pete Chen" Description="Demo Application" SummaryCodepage="950" />
  <PropertyRef Id="NETFRAMEWORK40FULL"/>
  <Condition Message="請先安裝Microsoft .NET Framework 4.0再安裝此軟體">
      <![CDATA[Installed OR NETFRAMEWORK40FULL]]>
  </Condition>

這邊要注意的是,PropertyRef及Condition節點一定要放在Package節點之後,否則無法建置WiX成功,因為根據XSD (C:\Program Files (x86)\WiX Toolset v3.7\doc\wix.xsd)的定義,Product節點後的第一順位為Package節點。


設定完成後建置出MSI檔並安裝在無安裝.NET Framework 4.0環境的主機,可以看到系統會出現警告視窗並停止安裝動作。



延伸閱讀


September 24, 2013

兩款WiX編輯器 - WiX Edit與SharpDevelop

WiX是一套用來封裝應用程式檔案成安裝檔(*.msi)的工具,它提供Visual Stuio專案樣板和編譯工具,讓開發人員在Visual Studio編輯完WiX所支援的XML格式設定檔(*.wxs)後,可以透過建置功能打包應用程式檔案。在前一間公司任職時,也是使用WiX並整合至CI Server進行自動化封裝。然而在設定上,WiX主要還是透過編輯XML設定檔來完成,相當不親民。


封裝機制其實VS也有內建專案樣板可以使用,也提供精美的編輯畫面,小巧好用且操作不難,我在最近一個小型的Windows Forms專案中,也嘗試使用這內建的封裝功能,以避免XML檔案編輯地獄,一開始效果還不錯,當要給測試人員測試時,我只要編譯一下方案檔來產出安裝檔送出去就好了。但在我試著把它整合至CI Server(Jenkins)中時卻發現MSBuild工具無法編譯*.vdproj專案檔,雖然有國外網友提出使用devenv.exe對整個方案檔做編譯來解決這個問題,但因為不打算在CI Server上安裝VS,所以我又回到了使用WiX。


以上全是題外話,和主題無關。既然再回到WiX的懷抱,就要想辦法爬出XML編輯地獄,所以找到了兩款WiX編輯器來輔助開發。

WiXEdit

WiXEdit是一套免費的WiX編輯器,目前的版本為0.7.5,不過它已經兩年多沒發佈新版本了。透過WiXEdit提供的GUI,可以輕鬆地選擇要加入封裝的檔案或資料夾。不過在使用上發現有個小缺點,就是右側的屬性是要自己手動去選擇新增。



SharpDevelop

SharpDevelop事實上不只是一套WiX編輯器,而是一套完整又開源的.NET開發工具,且目前仍持續在更新。相較於WiXEdit,SharpDevelop的GUI較為精美,操作上相對流暢,也不用自行新增屬性,SharpDevelop會自動載入可以設定的屬性名稱。


SharpDevelop也有內建的WiX專案樣板,如果不想在VS編輯WiX設定檔,也可以直接在SharpDevelop建立WiX專案開發。有興趣的朋友可參考WiX Integration這篇文章在SharpDevelop上建立自己的WiX專案,雖然文章已是七年前但設定沒有太大的差別。


這兩套工具我並沒有玩得很深入,因為目前的需求只要能把檔案封裝成MSI檔即可,所以基本上使用到的功能只有加入檔案或資料夾、設定桌面捷徑及開始選單捷徑、移除程式捷徑、網頁捷徑等。諸如安裝畫面客製化,安裝前後執行特定指令等功能尚未接觸到。

September 11, 2013

ToolTip Control in Windows Forms

Tooltip is often used as a hint or helper to tell application users what the functionality of a specific control is for or what will happen when they conduct operation on those controls, for instance, click a button.

In Windows Forms, you cannot set up the tooltip for a control until you drag a ToolTip control into the designer (you can create a ToolTip instance in the code though) and put your tooltip in the ToolTip on [ToolTip Control Name] property.




That being said, in some cases you will need to set up your tooltip PROGRAMMATICALLY. For example, in my case I want to display the tooltip on a button indicating a file path from a data source when the cursor hovers the button. We can leverage the ToolTip.Show method of the ToolTip control to assign the message being displayed to the button.
private void Button_OpenStonePhoto_MouseHover(object sender, EventArgs e)
{
    this.ToolTip_Photo.Show(@"C:\Users\Pete\Desktop\Pete.jpg", this.Button_OpenStonePhoto);
}

Alternatively, you can use the ToolTip.SetToolTip method to achieve the same, but note that the two methods have subtlety based on MSDN.
private void Form1_Load(object sender, EventArgs e)
{
    this.ToolTip_Photo.SetToolTip(this.Button_OpenStonePhoto, @"C:\Users\Pete\Desktop\Pete.jpg");
}

September 7, 2013

書評 - AOP in .NET: Practical Aspect-Oriented Programming

圖片來源:天瓏網路書店
Aspect-Oriented Programming (AOP)這名詞我大概是在兩三年前看過幾篇介紹文章知道的,但再更早之前AOP就已被提出來了。AOP主要是用來解決撰寫Cross-Cutting Concern時會遇到code duplication及混淆business logic等問題,如Logging、Caching、Validation等。在Java領域中,很早就有專書講解AOP在Java上的應用,而在.NET領域中雖然介紹文章不算少,尤其是隨著ASP.NET MVC的熱門,AOP在.NET的應用更為關注,但專門討論AOP的書這本應該算是第一本,而在它出版前我也注意它有一段時間。

本書除了介紹AOP的專有名詞及概念外,直接以兩套知名的.NET AOP Framework做為範例來介紹在.NET中如何實作AOP。這兩套Framework分別是Castle DynamicProxyPostSharp。這兩套的差別在於DynamicProxy是在run-time透過Proxy物件執行AOP,且DynamicProxy主要是和IoC container搭配實作;而PostSharp是在compile-time時由framework做IL weaving將Advice插入原始程式中。DynamicProxy是免費開源的,而PostSharp有分免費版和付費版。此外,這本書只有近300頁,搭配程式碼範例讀起很輕鬆也容易吸收。

我在最近的一個Windows Form專案中也參考了這本書使用PostSharp加入AOP的設計,讓Cross-Cutting Concern和Business Logic分離,程式碼精簡不少,Business Logic也乾淨了許多。如果有朋友想了解AOP,我相當推薦這本書做為參考。

September 5, 2013

Two-way binding in Windows Forms

Recently I've been involved in a small-scale project using Windows Forms, and I wondered if there's two-way binding implementation in Windows Forms, just kind of like what Knockout.js does in a web application.

Fortunately I do find what I wanted in Windows Forms. Controls such as TextBox, Combobox and others have a property called DataBindings which can help achieve two-way binding. I'm going to give a brief example below.

Here we have a view model, say, EmployeeViewModel, consisting of three properties.
public class EmployeeViewModel
{
    public string FirstName
    {
        get;
        set;
    }

    public string LastName
    {
        get;
        set;
    }

    public string PhoneNumber
    {
        get;
        set;
    }
}
Here's the form. We have three TextBoxes and two Buttons in the form. The three textboxes correspond to FirstName, LastName and PhoneNumber property in the EmployeeViewModel. The "Show me the view model" button will print out the values of the properties of the view model in the output window in Visual Studio, whereas the "Modify the view model" button will update the view model with hard-coded values.


In the form load event, we register the bindings between the Text property of texboxes and the FirstName/LastName/PhoneNumber property of EmployeeViewModel.
private void Form1_Load(object sender, EventArgs e)
{
    this.TextBox_FirstName.DataBindings.Add("Text", this._employeeViewModel, "FirstName");
    this.TextBox_LastName.DataBindings.Add("Text", this._employeeViewModel, "LastName");
    this.TextBox_PhoneNumber.DataBindings.Add("Text", this._employeeViewModel, "PhoneNumber");
}

Here's what the "Show me the view model" button does in the code. You can see that the code tries to print out the values of the properties of the view model in the output window.
private void Button_ShowMeTheViewModel_Click(object sender, EventArgs e)
{
    Console.WriteLine("First Name: " + this._employeeViewModel.FirstName);
    Console.WriteLine("Last Name: " + this._employeeViewModel.LastName);
    Console.WriteLine("Phone Number: " + this._employeeViewModel.PhoneNumber);
}

Compile the application and run it first. When you type in your first name, last name and phone number in those textboxes and click "Show me the view model", you see the magic. What does that mean? That means that you don't even need to grab values from the textboxes using TextBox.Text. You just get the values from the view model and print them out. With the binding, the modification on the textboxes will also apply to the view model.


Until now, I've actually achieved only one-way binding. What's the other "way"? Look at the code in the "Modify the view model" button.
private void Button_ModifyTheViewModel_Click(object sender, EventArgs e)
{
    this._employeeViewModel.FirstName = "Claire";
    this._employeeViewModel.LastName = "Chang";
    this._employeeViewModel.PhoneNumber = "+886928xxxxxx";
}

That simple? I just modify the view model and give it some hard-coded values. Hold on, what kind of result would I expect from just updating the view model? I would hope that when the values of the view model get changed, the values of textboxes will update accordingly. Let's compile and run the application again, then click "Modify the view model".


Oops! Nothing seems happened. Yes, you see nothing changed in the textboxes. In order to notify textboxes of the change in EmployeeViewModel, you will need to implement the INotifyPropertyChanged interface. Here's the code snippet for updated EmployeeViewModel that implements INotifyPropertyChanged.
public class EmployeeViewModel : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private string _firstName;

        public string FirstName
        {
            get
            {
                return this._firstName;
            }
            set
            {
                if (this._firstName != value)
                {
                    this._firstName = value;
                    NotifyPropertyChanged("FirstName");
                }
            }
        }

        private string _lastName;

        public string LastName
        {
            get
            {
                return this._lastName;
            }

            set
            {
                if (this._lastName != value)
                {
                    this._lastName = value;
                    NotifyPropertyChanged("LastName");
                }
            }
        }

        private string _phoneNumber;

        public string PhoneNumber
        {
            get
            {
                return this._phoneNumber;
            }
            set
            {
                if (this._phoneNumber != value)
                {
                    this._phoneNumber = value;
                    NotifyPropertyChanged("PhoneNumber");
                }
            }
        }
    }

Now run the application again then click "Modify the view model". You should see the magic again.


With two-way binding, you focus on your model or view model most of the time. When you update your controls, your model gets modified too and vice versa. However, registering the DataBindings for controls could be error-prone since you will have to hard-code the property name in your code as string. When you refactor the property names in the model in Visual Studio, those hard-coded property names will not be refactored accordingly. What's more, if you have a huge view model, you will to some degree have code duplication because of the INotifyPropertyChanged implementation. With the help of an advanced AOP tool like PostSharp, you can reduce the duplication gracefully. I'm not going to talk about AOP or PostSharp here because it's out of scope of this post.

August 27, 2013

工商服務 - IT Consultant

幫朋友徵才,意者可直接寄email或電話聯絡。


公司的亞太研發中心位於新加坡,是一家專精於高傳輸量的電子交易環境與e-game領先技術的方案解決者,應用核心技術來為客戶規劃,構建與開發高傳輸量的電子交易平台以支持其核心交易業務的發展。

為了因應快速的業務成長,目前積極地在台灣、越南、菲律賓、中國大陸,及歐洲建立不同的團隊,非常急需具備寬廣的國際視野與團隊合作能力的優秀人才加入。

產品:
應用核心技術為來自歐美亞的客戶規劃,構建與開發高傳輸量的平台以支持其交易業務的發展。服務項目包括C2C、B2B、 B2C、Internet game、and trading、 ...etc.

Job Title: IT Consultant
Job Description:
1. Assist Project Manager in project timeline estimation to predict accurate delivery of deliverables
2. Assist Project Manager in work package/component system design to ensure quality metrics are met in terms of maintainability, reliability, scalability and resilience
3. In charge of coding, testing and documentation in line with user & system requirements to deliver source code, documents and test scripts that meet clients’ needs
4. To perform 3rd level support in and after office hours to ensure fastest possible recovery to service
5. Constantly keep up-to-date in technological advancement and patterns to ensure skillset are relevant and ability to develop better quality products.
6. To work closely with to highlight any unplanned utilization pattern of self – this may include both under or over-utilization
7. To constantly update project plan to allow proper tracking of project status
8. Ensure and protect company intellectual property

Location:內湖科技園區

歡迎有興趣者與我聯繫,candice.lin@adecco.com or (02)7718-8834

工商服務 - Sr. SW Engineer

幫朋友徵才,意者可直接寄email或電話聯絡。


這是一家新加坡商,於民國100年在台設立分公司。
公司主要從事電腦軟體服務業,除服務全台及亞太區的客戶群外,同時兼為母公司之資訊系統創新、研發、維運及後勤中心。

母公司創立於2006年,針對亞太區客戶提供良好服務。集團目前致力於擴展業務範圍至全世界的各主要及次要代理服務。目前在全球於新加坡、台灣、英國、香港及菲律賓設有據點,並因應快速成長的業務範圍積極擴展中。

主要產品:
1.各類運動賽事比賽前、後端分析軟體研發。
2.集團全球各地網站前後台設計、維運。
3.客製化Win Form Client AP開發以及後台維運。
4.客製化Web Based App 開發以及後台維運。
5.集團資訊中心監控維運。

Job Title: Sr. SW Engineer
Job Description:
1. .net技術的系統開發
2. 負責系統架構設計、資料庫設計及系統核心代碼撰寫

Requirement:
Experience with B/S development.
1.  Above 3 years .net develop experience
2. Familiarity with SQL SERVER 2008/2012
3. Experience with DBA
4. Familiarity with SQL Server and familiarity with PL/SQL.
5. Experience with .NET Framework, and able to develop C/S and B/S appliances independently.

Location:內湖科技園區

如有興趣者,歡迎與我聯繫,candice.lin@adecco.com or (02)7718-8834,謝謝!

August 26, 2013

工商服務 - 系統整合工程師

幫朋友徵才,意者可直接寄email或電話聯絡。


這是一家外商公司,全球遍佈8大國,共7000名員工。台灣分公司創立於民國 87 年,主要從事高速資料處理/電子資料供應服務;客戶均為銀行、金融機構、保險公司等。現階段因業務擴展,已陸續增加不同產業的客戶,例: 流通貨運業。

公司地點在汐止遠東世界中心

交通方式:
捷運:可坐至南港展覽館站, 再轉搭藍15公車坐三站即可抵達
火車:可坐至汐科站, 有專門捷徑可走路抵達遠東世界中心

職稱:系統整合工程師

工作內容:
1. 作業流程規劃與設計
2. 文件數位化系統開發與維護
3. 文件儲存系統開發與維護
4. 使用者教育訓練

職缺需求:
  1. 三年以上系統開發實務經驗
  2. 熟悉 ASP.NET / C# .NET, JavaScript / AJAX, XML 程式設計與開發,或是熟悉Java, Servelt, JSP等 J2EE WEB程式設計與開發
  3. 熟悉資料庫管理與維護, MS SQL, MySQL, DB2
  4. 具有掃描開發技術者尤佳
  5. 具有系統開發流程經驗者尤佳, 如使用 CMMI, 軟體工程
  6. 英文聽說讀寫中等程度, 能與國外做基本溝通者尤佳
薪資:年薪70~100萬,保障13個月

聯絡方式: Candice.lin@adecco.com or (02)7718-8834

August 4, 2013

使用Entity Framework操作SQLite

最近支援開發一個使用SQLite的單機應用程式,並使用Entity Framework來加速data access layer開發,以下記錄在Visual Studio 2010 Professional中如何設定Entity Framework來操作SQLite。

安裝VS 2010所需設計元件

System.Data.SQLite Download Page下載於VS 2010開發時所需的元件安裝檔sqlite-netFx40-setup-bundle-x86-2010-1.0.87.0.exe安裝檔。安裝過程中需勾選Install the designer components for Visual Studio 2010



安裝Entity Framework

透過以下nuget指令安裝Entity Framework

Install-Package EntityFramework


安裝System.Data.SQLite

透過以下nuget指令安裝System.Data.SQLite

Install-Package System.Data.SQLite

安裝完後在References中會看到System.Data.SQLiteSystem.Data.SQLite.Linq,專案內會新增兩個資料夾x64和x86,兩個資料夾內各有一個名為SQLite.Interop.dll的檔案。


建立ADO.NET Entity Data Model

在專案中新增一個ADO.NET Entity Data Model項目




點選New Connection,將Data source選取為System.Data.SQLite Database File,Data provider為.NET Framework Data Provider for SQLite


點選New,建立一個SQLite資料庫,如果資料庫已存在則點選Browse找出資料庫存在路徑即可。



設定完成後,在專案中會新增一個*.edmx檔案。在Server Explorer中也可以連線到剛建立的SQLite資料庫,讓我們可以在VS上操作資料庫。在這裡先建立一個測試用的資料表Log和其兩個欄位分別為LogId及LoggedOn。



更新Entity Data Model (*.edmx),可以看到資料表Log已被放入Entity Data Model中


安裝EF 5.x DbContext Generator for C#擴充樣板

這個步驟不是必須,但如果希望Entity Framework產生的是POCO類別的話透過這個擴充樣板便可輕鬆完成。至Extension Manager (Tools-> Extension Manager)中搜尋poco,便可看到EF 5.x DbContext Generator for C#選項並進行安裝。


安裝完成後回到*.edmx,右鍵選取Add Code Generation Item,選擇EF 5.x DbContext Generator for C#並為樣板命名


按下Add後便會開始產生POCO類別,可以在專案下看到*.tt*.Context.tt兩個新增檔案。*.tt裡的Log.cs即是對應資料表Log產生的POCO類別。


測試程式

執行以下程式,便可將資料新增至SQLite資料庫中
using (DemoEntities context = new DemoEntities())
{
    context.Logs.Add(new Log { LogId = Guid.NewGuid(), LogedOn = DateTime.UtcNow });
    context.SaveChanges();
}



部署注意事項

將應用程式部署到測試機上,執行後出現The specified store provider cannot be found in the configuration, or is not valid.錯誤訊息。更細部的錯誤訊息為Unable to find the requested .Net Framework Data Provider.  It may not be installed.


加入以下設定至設定檔<configuration>區段中即可解決此問題
<system.data>
    <DbProviderFactories>
        <remove invariant="System.Data.SQLite"/>
        <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.87.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139"/>
    </DbProviderFactories>
</system.data>

1.0.87.0是我所使用的System.Data.SQLite元件版本。

July 31, 2013

書評 - Head First Design Patterns

圖片來源:天瓏網路書店
對於這本書,我只有相見恨晚四個字可以形容。

初入Design Patterns是在工作的第一年,由於當時公司資深同事兼研究所學長推薦GoF寫的Design Patterns: Elements of Reusable Object-Oriented Software,所以買了它的中文版物件導向設計模式來研讀。然而當時功力尚淺,整本讀完了但大部份的Patterns有看沒有懂。

工作三年多,累積了一些實戰經驗後,興起了複習Design Patterns的念頭。由於GoF版本對我來說有點難吸收,便找了C# 3.0 Design Patterns來看,並搭配GoF版本做參考一同服用。這次好多了,範例程式是用C#撰寫,好懂一點,但對Design Patterns的認知程度仍只有些許提升。

現在工作六年了,再次興起複習的念頭,而這次找來的是Head First系列書的Design Patterns。本書在Amazon上有極高的評價,範例是以Java撰寫,但對C#開發人員閱讀起來應該沒什麼問題。每個Pattern以說故事的方式來呈現,前因後果互相串連,加上圖例說明。雖然有六百多頁,但讀起來很快也很好理解。

GoF版本中有23個Patterns,而在Head First Design Patterns主要描述GoF中的14個Patterns,再加上MVC Pattern、SOLID原則中Single Responsibility PrincipleOpen-Closed PrincipleDependency Inversion Principle,其餘9個Patterns則放在Appendix裡做簡單的說明而已。此次讀完Head First Design Patterns,對其描述的14個Patterns理解度加深不少,且對於原本在讀GoF版本時產生的一些誤解也有所釐清。如果有朋友想初入Design Pattern的話,我推薦先閱讀Head First版本,再輔以GoF版本做參考,效果會比較好。