Monotasking
Slide link Monotasking 排定優先序 沒有都很重要這種事 治好延遲病 避免多任務切換 拉金問題 找回生活的節奏 Pomodoro 維持專注力 結合看板使用 Kanbanflow
Slide link Monotasking 排定優先序 沒有都很重要這種事 治好延遲病 避免多任務切換 拉金問題 找回生活的節奏 Pomodoro 維持專注力 結合看板使用 Kanbanflow
前言 Serilog 是一款給 .NET 平台的 Log Library ,它最大的特色應該是使用事件來驅動,而不是單純的寫下 Log ,這點讓它跟其他的 Library 有很大的不同,而他所提供的多樣Sink讓這點的發揮更加強大。他可以做到同時記下 Log ,發送信件,存到DB並且傳到 Slack 中通知維運人員,這些事情都可以在記下 Log 時一併做完,只需要設定一次。這點是我覺得這個 Library 最強大的地方。 source code 內文 Serilog 除了可以在 .NET 平台使用外,他還支援了 .NET Core ,這讓它在非 Windows 平台上的使用是可能的, Source Code 跟以下的文章就是在MAC環境下搭配 .NET Core 使用 Serilog。 開啟一個新的專案後在 Dependencies 按下右鍵選擇 Add Packages,再使用關鍵字「Serilog」查詢~ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 /// <summary> /// My logger. /// </summary> public class MyLogger { /// <summary> /// The logger. /// </summary> private ILogger _logger; /// <summary> /// Initializes a new instance of the <see cref="T:BenSerilogNlog.MyLogger"/> class. /// </summary> public MyLogger() { ////最基本的建立Logger的方式 this._logger = new LoggerConfiguration() .WriteTo.Console() .CreateLogger(); } /// <summary> /// Logs the info. /// </summary> /// <param name="message">Message.</param> public void LogInfo(string message){ this._logger.Information(message); } } 呼叫端可以這樣使用 ...
前言 使用 Git 也有一段時間了,但是一直以來都很依賴使用 GUI 來幫忙做事情,甚少使用指令。 在一次 GUI 改版後因為使用 GUI 的回應速度真的是太慢了,所以才開始學習使用指令來做事,也是這時才發現原來使用指令沒有想像中麻煩,也如預期中的非常快速。 因此這邊就我自己的使用心得來分享,也因為我在使用 git 指令時有很多設定是已經在安裝 GUI 時就設定完畢的,所以這邊的常用指令其實是就我個人使用上而言。 像是有很多 remote repository 的設定我不是使用指令來完成的,這部分的指令就之後有機會再補上了。 安裝 下載路徑:https://git-for-windows.github.io/ GUI:https://git-scm.com/downloads/guis 下載安裝檔後基本上用預設值並一直按下下一步就好 [圖 Install-1] [圖 Install-2] [圖 Install-3] 在 Powershell 更輕易的使用 Git(posh-git): 使用 PsGet 安裝 PsGet => Powershell安裝套件的好幫手 posh-git => 在 powershell 使用 git 的好幫手 1 2 (new-object Net.WebClient).DownloadString("http://psget.net/GetPsGet.ps1") | iex Install-Module posh-git [圖 Install-4] 但若使用這種方式安裝,每次關掉 powershell 要再使用就需要先下個 1 Import-Module posh-git 才能使用。若不想這麼麻煩的話,打開一個新的 powershell prompt 直接輸入 1 Add-PoshGitToProfile 這樣就可以免除每次關掉都要再 import module 的窘境。 ...
前言 會有這個文章主要是因為,有需要比對序列化後字串是否符合預期的情境,但是卻因為沒有注意到這點讓測試程式碼怎樣都過不了 Orz 這個問題坦白說,若沒有踩到還真不會特別去計較這件事。關於 BOM(位元組順序記號),就我的實務經驗來講是很少會使用到的資訊,尤其是最常用到的編碼方式為 UTF-8,一般來說我不會馬上想到這個方向。 而 UTF-8 with BOM 的檔案基本上跟 without BOM 用肉眼是看不出差異的,只會在使用游標左右移動時發現需要多按一下才會動,在精神不濟時會以為這些都是幻覺 XD。但若是用 Notepad++ 的話,可以開啟 16 進位的檢視,就能看到 UTF-8 BOM 的那該死的位元組「ef bb bf」,在 windows 平台上有時可以看到存檔時可以選擇是否要包含 BOM 這個選項。 實驗 在 XmlTextWriter 實體要 new 出來時會有幾種作法,其中我們要講的就是把 Encoding 方式傳入的那種。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class SerializeHelper { /// <summary> /// 序列化物件編碼 /// 序列化後文字 /// </summary> public string Serialize(object o, Encoding encoding) { XmlSerializer xmls = new XmlSerializer(o.GetType()); var xns = new XmlSerializerNamespaces(); xns.Add(string.Empty, string.Empty); using (MemoryStream ms = new MemoryStream()) { using (var writer = new XmlTextWriter(ms, encoding)) { xmls.Serialize(writer, o, xns); } string xml = Encoding.UTF8.GetString(ms.ToArray()); return xml; } } } 文字是否有加入 BOM 一般來說很難用肉眼看出來有什麼差異,因此我們使用 GetByteCount 來識別是否有 BOM 參入其中,看看是否真的多了那三個該死的位元標記符號。 ...
前言 現在有很多系統除非太小,不然應該都會使用第三方開發的 DI 容器,來實現 IoC。但是使用 DI 容器時免不了要對於物件的生命週期有一定的了解,不然到時候出現相關的問題就手忙腳亂了。因此這一篇文章就記錄了我使用 Autofac 時,遇到的 memory leak 的問題,並把所做的實驗記錄下來。 實驗的情境主要是 run 在 console 環境中,模擬類似 windows service 的情境,所以 web 的 ASP.Net 環境並不在此實驗的考慮範圍內。 這篇文章使用的原始碼連結如下(已更新專案為 .NET 5): GitHub repo url 內文 物件的生命週期與最初註冊物件的依賴是怎樣的方式,預設是 InstancePerDependency 這個方法,它會確保你每次呼叫 Resolve 方法時可以取得新的物件,並不會與其他呼叫端使用同一份實體。這個特性在大多數的時候都會符合需求。 因此在注入時我們先這樣寫: ps.快照時間基本上都是10秒30秒各拍一次,執行超過50秒就結束實驗。 實驗一 1 2 3 4 5 6 7 8 9 10 public class DAModules : Autofac.Module { protected override void Load(ContainerBuilder builder) { var assembly = Assembly.Load("NineYi.ERP.DA.ERPDB"); builder.RegisterType<deamonresourcerepository>() .As<ideamonresourcerepository>() .InstancePerDependency(); } } 接下來就是我們這次的實驗目標的寫法: ...
前言 Windows 的用戶可以很輕易的用提供的介面更換登入畫面與桌面的圖片,但是 MAC 的用戶可就沒這麼方便了,預設會是桌面圖片的模糊化圖片,這篇教學是讓大家可以很輕易的把登入畫面換成自己喜愛的圖片。 內文 預設上,MAC 會用桌面的圖片模糊化後作為登入的畫面,這個行為 MAC 並沒有提供介面作調整(而且也沒有相關的 command 啦),但是它卻會把桌面的圖片模糊化後複製一份到資料夾中方便他作存取,所以理論上把這張圖換掉並不會影響桌面的圖片但是可以成功把登入畫面的圖片換成自己的,那我們就來試試看吧~! 在 Finder 中按下: Shift+Command+G 輸入: /Library/Caches 注意!預設會是 “~/Library/Caches” 這個是你自己的資料夾底下的 Caches 資料夾,我們要找的是系統的,所以要把前面的相對符號給拿掉! 你應該會在這個資料夾中找到名為:「com.apple.desktop.admin.png」的圖片,而且會與目前你的桌布圖片模糊化後相同。 接下來要作的事情就很直覺了, **STEP1:**找一張你喜歡的圖片(要PNG格式的喔!) **STEP2:**把他複製到該資料夾中並用「com.apple.desktop.admin.png」名稱儲存 **STEP3:**當他跳出警示視窗時按下確定,覆蓋掉原本的圖片 **SETP4:**登出後重新登入就可以看到成果了~! 祝大家換圖開心啦~! 成果 Login Desktop
前言 距離之前在 Mac 上面 run .NET 程式還過沒多久,微軟的腳步越來越快,現在已經推出在 Mac 平台的編輯器了,雖然目前看來還有不少缺乏的東西,但是依照目前微軟的腳步我想應該過不了多久應該就會補上了。這樣越來越多的時間要花在追技術與新工具上了 XD 內文 如果是之前完全沒裝過 kvm 的人會比較簡單,畢竟之前的 kvm 已經用不到了,另外就是之前的 kre 版本在 beta2 與 beta3 經歷過一次變化,讓存放的路徑有所變化,所以對一路追的人來說,這次要把 kvm 相關的東西移除會比較費事些 移除舊有的kvm 1 brew uninstall kvm 移除舊的執行環境 1 rm -rf ~/.k ~/.kre ~/.kpm ps. .k這個目錄是 beta3 時的新目錄 安裝 DNVM (其實安裝步驟跟之前安裝 kvm 是一樣的,不用記特別的安裝步驟是個好消息 XD) 1 2 brew tap aspen/dnvm brew install dnvm 更新 dnvm 1 2 dnvm upgrade dnvm upgrade -u ps.預設這個指令會去抓最新的 stable 版本的 dnx,但是目前因為尚未有 release 的版本所以要帶上 “-u” 抓取 unstable 的版本。 ...
前言 .NET 已經 OpenSource 了!但我相信這個消息早就不是新聞了,國外也有很多人分享了如何在很潮的 Mac 上寫 .NET 應用。只是英文的教學很多但是中文的卻很少,趁著機會趕緊分享一下自己在 Mac 上面安裝 .NET 開發相關環境的心得。 內文 由於 ASP.NET 已經正式 OpenSource 了,原始碼都放在 GitHub 上而且官方教學也是放那裡,因此我們就從官方的教學來一步步完成吧。 官方連結 安裝KVM 首先,要去安裝 KVM(K Version Manager) 這是一個幫助管理 KRE(K Runtime Environment) 的工具,我們可以在同一時間安裝不同版本的 KRE 並且指定目前預設的 KRE 是哪一套。KVM 我們可以用 HomeBrew 安裝,因此安裝方式超簡單。 下以下 command 把這個 GitHub Repos 加入 HomeBrew 的追蹤裡。 1 brew tap aspnet/k 接著run以下的command安裝KVM 1 brew install kvm 接下來依照指示在bash_profile中加入source kvm.sh 1 vim .bash_profile 安裝KRE 裝好 KVM 後執行 upgrade ...
前言 接續上次的文章,我們這次要把要一步一步把功能給實做完成~! 第一階段 第二階段 內文 延續上次的文章,我們已經完成 Todo 應用的 CUD(新增、修改、刪除),接下來我們要做的便是可以讓使用者 filter 已經完成的 Todo,哪些又是尚未完成的 Todo。因此這邊我們需要把我們的 Template 分成數個子 Template 並利用框架的 Route 來做到讓這些事情在同一頁完成。 首先我們先把列表頁的內容抽出來變成一個新的 Template 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <!-- data-template-name內的值就相當於是一個路由,index是讓這個Template顯示的路由值,裡面的資料來源從哪裡來則從route去設定 --> <script type="text/x-handlebars" data-template-name="MyTodos/index"> <ul id="todo-list"> {{#each itemController="MyTodoList"}} <li {{bind-attr class="isCompleted:completed isEditing:editing" }}> {{#if isEditing}} {{input class="edit" value=title focus-out="acceptChanges" insert-newline="acceptChanges"}} {{else}} {{input type="checkbox" checked=isItemCompleted class="toggle"}} <label {{action "editTodo" on="doubleClick" }}>{{title}}</label><button {{action "removeTodo" }} class="destroy"></button> {{/if}} </li> {{/each}} </ul> </script> 而原本的 Template 就變成如下: ...
前言 接續上個月(拖好久…)的進度我們繼續把這個簡單的應用給完成吧~ 第一階段 第一階段我們只是把最簡單的 Model 型態完成,但是卻還沒賦予 Model 跟 View 互動的機制,這階段就是要完成可以對 TodoList 的項目進行編輯以及把項目標示為已完成。 內文 首先我們先完成選取在每個項目前面的勾勾就把該項目給畫上一個橫線表示完成的功能。在這個功能中我們會需要對列表的每個項目進行操作,我們的 HTML 一開始是長這樣的: 1 2 3 4 5 6 {{#each}} <li {{bind-attr class="isCompleted:completed"}}> <input type="checkbox" class="toggle"> <label>{{title}}</label><button class="destroy"></button> </li> {{/each}} 在這裡我們可以新增一個 controller 來 wrapping 每個 each 裡的項目( Ember 裡的 controller 管理狀態與跟畫面的互動, manage state and decorate data),新的 controller 內容如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 Todos.MyTodoListController = Ember.ObjectController.extend({ // 類似 Knockout.js 的 Computed property,這個屬性會依照相依的屬性值的變化而改變 // 是否完成 isItemCompleted: function (key, value) { var model = this.get('model'); if (value === undefined) { // Getter, 把目前項目的 isCompleted 回傳 return model.get('isCompleted'); } else { // Setter model.set('isCompleted', value); model.save(); // 更改項目的 isCompleted 值 return value; } }.property('model.isCompleted') // 或也可以寫成如下方式: // 這個寫法看起來比較明確點 isItemCompleted: Ember.computed('model.isCompleted', function (key, value) { var model = this.get('model'); if (value === undefined) { // Getter, 把目前項目的isCompleted回傳 return model.get('isCompleted'); } else { model.set('isCompleted', value); model.save(); // 更改項目的isCompleted值 return value; } }) }) 這個isItemCompleted屬性後面呼叫了property方法,這相當於宣告這個屬性是一個computed property。 然後在前端的html我們改成這樣: ...
前言 時間回到三年前(2011年)…那個時候做 Web Application 在前端 Framework 的選擇不像現在多的眼花繚亂,基本上套上 jQuery 與 jQuery UI 還有一票 jQuery 的徒子徒孫就是火力強大的工具了,那個時候也是我第一次使用完整的前端 framework solution。時間沒走多久前端的需求爆炸性的成長,只用 jQeury 來操作 DOM 元素已經不敷需求,另外用 jQuery 來做 SPA 要手工的地方太多也挺吃力的,所以很多 SPA 的框架就誕生了。目前最多人擁護的莫過於 AngularJS,而後起之秀 EmberJS 雖然也是有不少擁護者但就台灣的環境來說 AngularJS 已獲得壓倒性的勝利,一方面是因為 AngularJS 發展穩定,又有 Google 這個大公司當靠山,所以網路上的資源比任何 SPA Framework 都還要多。但我就是比較搞怪一點所以就選 EmberJS 來看看了 XD。目前 EmberJS 是 Open Source 的專案 host 在 GitHub 上 EmberJS EmberJS 相對於 AngularJS 變化比較大所以需要多關注 GitHub 上面的 Issues 或是 commits,有些時候官網上面的教學文件還落後最新的 Stable 版本一段差距。 本文 這篇文章會以官方的 Todo 教學為實現的功能,功能會到讓這個 Todo 應用可以塞入新的 Todo 事項,當中會加上一些我對它的理解。這個 EmberJS Application 會用到幾個 libary,jQuery + Handlebars + Ember + Ember-Data 這其中 handlebars 至個 libary 還滿特別的,有用過 AngularJS 的人一定對他的功能不陌生,它其實就是一個讓我們可以方便建構語意式模版的工具,用法像是以下這樣: ...
前言 這篇文章主要講的是 DI 常見的方式,共四種模式這邊首先介紹最為常見的建構子注入。其實 DI 這個技巧我們常常都會使用到,甚至就算你不知道也會用它,雖然是什麼相當偉大的技巧但是卻是很實用也很重要的技巧。DI(Dependency Injection , 依賴注入),講的是針對抽象來撰寫程式而非實體。底下會有範例來展示這項技巧。另外,這篇文章主要是依照 Dependency Injection in .NET 這本書的內容來撰寫的,但有部分觀點屬於個人。 內文 Constructor Injection (建構子注入) 這個模式應用很廣泛也是很容易實現的一個DI模式,在使用這個模式時會需要類別提供一個公開(public)並且需要一個實體作為參數的的建構子,通常的情況下這個類別只會有這麼一個建構子的存在,另外,請儘量避免overload建構子,保持只有單一一個建構子的情況。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //實現 Constructor Injection 的類別 public class MyFirstDIClass { // DI 欄位是readonly可以在類別初始化後避免被修改。 private readonly AnimalRepository repository; public MyFirstDIClass(AnimalRepository repository) { // 確保注入的實體是存在的 if(repository == null) { throw new ArgumentNullException("repository"); } this.repository=repository;// 注入依賴的實體 } } 通常所要求輸入的參數會是一個抽象類別或是一個介面(abstract class or interface),之所以使用這兩種 Type 是因為建構子可以不用去管真正實現的類別究竟為何,只要這個類別繼承或是實作指定的 Type 即可,因為對於這個注入的實體也只會使用到指定 Type 所提供的公開方法而已。 在使用這個方法時有個需要注意的地方,要儘量避免在建構子中撰寫其他的邏輯。建構子裡面最好就是只有建構這個類別時所需要的邏輯即可,所有初始化這個類別以外的邏輯都不應該出現在這裡,簡單來講就是維持建構子的單純。 一般來說 Constructor Injection 這個方式的優缺點為 ...
前言 一般來說在.net中實現加密時我們會使用 RSACryptoServiceProvider 這個類別來實現產生公私鑰進行加解密的行為,而且一個簡單的 [ToXMLString()]](https://docs.microsoft.com/zh-tw/dotnet/api/system.security.cryptography.rsa.toxmlstring?view=netframework-4.7.2) 方法就能把公鑰(或甚至是私鑰,但實務上很不建議)給吐出來。不過除了使用這個類別來產生鑰匙外我們其實還可以利用強式名稱工具來幫我們產生鑰匙,好處是不但可以作為加解密的鑰匙來源,沒有金鑰容器名稱以及存取層級(User Layer, Machine Layer)的管理 issue 簡單用,還可以順便用它來簽署組件,一檔多用資源徹底利用。以下就是利用強式名稱工具來實作的方式。 內文 強式名稱工具(Strong Name Tool) 是安裝 Visual Studio 之後就會附上的開發用工具我們可以開啟 “Visual Studio x64 Win64命令提示字元”,鍵入 “sn.exe /?” 來觀看可以使用的參數,這裡我們會用到的就是最簡單的 -k 參數而且就是使用 default 值。我們就利用這個工具產生一組全新的 snk 檔案放在 D 槽吧~ 我們已經可以在D槽的跟目錄下面看到產生好的 Strong Name Key File 了~ 要注意的是使用預設的話 key size 長度就是 1024 bit 這長度與能拿來加密的文字長度會有直接關係使用預設長度的話一次能夠加密的文字長度為 128bits,不過要小心在 .net 中會有 padding 的 issue 造成實際上可以加密的文字長度會更短(註一),這個問題的解決方式我們會在稍後的範例中看到。 準備好之後我們就來開啟一個專案試試看這 snk 檔要怎麼幫我們加密資料吧~ 我們這邊就使用最單純的 Console 專案來進行測試即可~ ps.這邊記得把 D 槽根目錄中的 snk 檔案放在專案的 bin 資料夾底下。 ps2.為了保持目的單純不小心類別就被搞大了… 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 using System; using System.Collections; using System.IO; using System.Security.Cryptography; class Program { private static string _strongNameKeyFile = "Test.snk"; public static string GetPublicKey { get; private set; } private static string GetPrivateKey { get; set; } public static string Data(string plaintext) { using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { rsa.ImportCspBlob(File.ReadAllBytes(_strongNameKeyFile)); GetPublicKey = rsa.ToXmlString(false); GetPrivateKey = rsa.ToXMLString(true); // base-64 encoded. return Convert.ToBase64String(EncryptData(plaintext)); } } // 若資料量很大的話(資料量小以預設來說就是資料量小於117 bits,那可以直接呼叫Encrypt()來進行加密及可) // 就需要分段加密不然一定會炸掉,吐一個Bad Length的例外訊息。 private static byte[] EncryptData(string rawdata) { // 憑證的金鑰預設就是1024 bit // buffer扣去11 bits是為了padding使用,請參考註一的連結。 const int encryptionBufferSize = (1024 / 8) - 11; const int DecryptionBufferSize = 1024 / 8; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); // 這邊利用公鑰來加密,因此解密的一方需要取得密鑰才能解密,這樣可以確保有私鑰的人才有辦法看到資訊。 rsa.FromXmlString(GetPublicKey); // 進行加密時都需要把字串轉成byte陣列來操作,這邊需要注意轉換的問題! byte[] dataEncoded = System.Text.Encoding.UTF8.GetBytes(rawdata); using (MemoryStream ms = new MemoryStream()) { byte[] buffer; int pos = 0; int copyLength = encryptionBufferSize; while (true) { if (pos + copyLength > dataEncoded.Length) copyLength = dataEncoded.Length - pos; buffer = new byte[copyLength]; Array.Copy(dataEncoded, pos, buffer, 0, copyLength); pos += copyLength; // 這邊不使用OEAP padding,使用 PKCS#1 v1.5 padding(填補法的差異請參考註一) // 另外也要注意雖然加密的資料需要扣除 padding 量,但是寫入的長度依然不變。 ms.Write(rsa.Encrypt(buffer, false), 0, DecryptionBufferSize); Array.Clear(buffer, 0, copyLength); if (pos >= dataEncoded.Length) break; } return ms.ToArray(); } } public static string GetPlainDataBack(string encryptdata) { string result = string.Empty; using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { const int decryptionBufferSize = 1024 / 8; // 使用公鑰加密就必須用私鑰解密。 rsa.FromXmlString(GetPrivateKey); byte[] encryptdataarray = Convert.FromBase64String(encryptdata); using (MemoryStream ms = new MemoryStream(encryptdataarray.Length)) { byte[] buffer = new byte[decryptionBufferSize]; int pos = 0; int copyLength = buffer.Length; while (true) { Array.Copy(encryptdataarray, pos, buffer, 0, copyLength); pos += copyLength; byte[] resp = rsa.Decrypt(buffer, false); ms.Write(resp, 0, resp.Length); Array.Clear(resp, 0, resp.Length); Array.Clear(buffer, 0, buffer.Length); if (pos >= encryptdataarray.Length) break; } result = System.Text.Encoding.UTF8.GetString((ms.ToArray())); } } return result; } static void Main(string[] args) { var plaintext = "This is a plain text!"; var result = Data(plaintext); Console.WriteLine("Orignal Text:{0}", plaintext); Console.WriteLine("After Encryption:{0}", result); result = GetPlainDataBack(result); Console.WriteLine("After Decryption:{0}",result); Console.Read(); } } 結語 以上就是使用強式名稱工具來達成資訊加密、解密的需求,我們可以發現若對方要可以解讀這個密文那 snk 檔是對方勢必得取得的檔案,因此該檔案的存取是一定要控管的,這是不方便之處。另外其實實務上除了加解密之外還會順手做數位簽章….這就留到下次吧… ...
開發 ASP.NET Web Form 的工程師對於網頁生命週期(Page Life Cycle)一定要熟記在心中,也要知道每個循環中的會發生的個事件的主要目的,才不會在需求要修改或是出現Bug時不知道該往哪裡找問題。不過,講是這樣講其實 ASP.NET 的網頁生命週期需要注意的細節是滿多的,而且一個週期內會發生的事件可能比你想像中的還要多。 一般來說網頁生命週期會經過 網頁要求 => 開始 => 初始化 => 載入 => 回傳事件處理 => 呈現 => 卸載 資料來源 表一:MSDN 一般網頁生命週期階段 Page Life Cycle 階段 說明 網頁要求 在網頁生命週期開始前會發生網頁要求。當使用者要求網頁時,ASP.NET 會判斷是否需要剖析和編譯網頁 (因此開始網頁的生命週期),或是可以在不執行網頁的情況下,傳送網頁的快取版本做為回應。 開始 在開始階段,會先設定網頁屬性,如 Request 與 Response。在這個階段中,網頁也會判斷要求是否為回傳或是新的要求,然後設定 IsPostBack 屬性。網頁同時也會設定 UICulture 屬性。 初始化 在網頁初始化期間,可以使用網頁上的控制項,並且設定每個控制項的 UniqueID 屬性。如果適用,也會將主版頁面與佈景主題套用到網頁。如果目前的要求是回傳,則尚未載入回傳資料,並且控制項屬性值並未還原至檢視狀態提供的值。 載入 在載入期間,如果目前的要求是回傳,就會使用從檢視狀態和控制項狀態復原的資訊載入控制項屬性。 回傳事件處理 如果是回傳要求,會先呼叫控制項事件處理常式,然後才會呼叫所有驗證程式控制項的 Validate 方法,以設定個別驗證程式控制項與網頁的 IsValid 屬性。 呈現 在呈現前,會儲存網頁和所有控制項的檢視狀態。在呈現階段,網頁會呼叫每個控制項的 Render 方法,藉此提供文字寫入器將其輸出寫入網頁之 Response 屬性的 OutputStream 物件。 卸載 完整呈現網頁之後,會引發 Unload 事件,然後傳送至用戶端予以捨棄。此時將會執行網頁屬性 (如 Response 與 Request) 的卸載及清除工作。 而在這樣的生命週期階段中會有數十個事件依序發生,而不論是作為網頁容器的 Page 類別或是使用者控制項(User Control)或是伺服器控制項(Server Constrol)幾乎都有相對應的事件。 Page 頁面是每個 Web Form 都會繼承的類別,依據需求上面也可以放置自行撰寫的使用者控制項(User Control),或是裡面也可以直接擺上 Server Control,因此我們可以把這個類別是為一個容器,裡面可以擺放很多顯示用的控制項,而這個控制項裡會有很多事件會在一個 request 進來後依序引發,以下就是網頁生命週期的「生命週期事件」: ...
使用 Entity Framework 的 Code First 來做資料存取層與既存資料庫溝通時多少都會遇到資料庫 Schema 變更的時候,只是這個時候若是有用到 Code First 來新增表格的話就會遇到像上一篇一樣的問題;執行時期使用資料庫的話會引發錯誤訊息,而且會通知因為資料庫的 Schema 變更需要使用 Migrations 來解決問題。因此這篇文章就是要來說明一般來說使用 Code First 來開發遇到資料庫 Schema 要變更時的正規作法應該怎麼做。 我們就用上一篇所生出來的資料庫來實作看看吧~ 不過為了方便起見,我們就直接先把 Products 這個資料表先刪除,我們來看看用 Code First 的方式開發的話若要新增一個資料表的正規方式是什麼?(這邊正規也只是我在講而已,只是這麼做的話可以免除之後的麻煩) 首先我們要先打開套件管理員的命令列視窗「Tools => Library Package Manager => Package Manager Console」,然後要用 Migrations 的話就要先把功能打開,需要下這樣的指令: 1 PM >> Enable-Migrations ,成功的同時我們的專案會新增一個 Migrations 資料夾,並且會給你一個 Configrations.cs 類別,若沒有要使用自動 Migrations 的話就可以先不用動這個類別的內容。接下來因為需求異動的關係我們需要多一個 Products 資料表來儲存產品的資訊。 Products 的資料表如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /// 產品的實體。 [Table("Products")] public class Product { /// 產品的識別號。 [Key] [ScaffoldColumn(false)] public int ID { get; set; } /// 產品的名稱。 public string Name { get; set; } /// 產品的價格。 public double Price { get; set; } /// 生產產品的工廠名稱。 public string FactoryName { get; set; } } 對於資料庫的 Schema 的異動我們可以在 Package Manager Console 中輸入 Add-Migrations xxxxxx xxxxxx就是新增的類別的名稱,通常會是這次異動的表格、欄位的名稱像是 AddProducts 之類的。這邊我是用 AddTableProducts ...