2017年6月25日 星期日

[EF] 使用Entity Framework code first紀錄

● VS 2013與EF6預設沒有code first精靈,該如何解決?
Ans: 安裝Entity Framework 6 Tools for Visual Studio 2012 & 2013

● 不透過精靈,使用code first建立新的資料庫?
to be continued...

2017年5月30日 星期二

[.Net/C#] foreach如何存取集合(Iterator/IEnumerable/IEnumerator/yield return)

說明:
foreach是用來對集合元素做巡覽/列舉的動作,透過Iterator來實作,
而Iterator是一種模式,在不暴露集合類別下,提供對集合類別依序巡覽的方法,
在.Net裡,已經將Iterator包好了,實作IEnumerable與IEnumerator即可。


什麼是IEnumerable?看下圖可知實作此介面提供一方法GetEnumerator(),
讓我們可以取得集合元素。



那IEnumerator呢? 提供實作iterator所需的方法與屬性。



也就是使用foreach in,編譯器會去找要巡覽的集合類別裡的GetEnumerator(),
然後執行IEnumerator內的MoveNext(),若回傳True,再取Current的值,
直到MoveNext回傳為False。


C# 1.0實作:
想巡覽Book集合類別,需實作IEnumerable與IEnumerator。







C# 2.0提供IEnumerable與IEnumerator的泛型,
可傳入巡覽元素的型別,減少裝箱與型別轉換的問題,
(因Current非泛型版本回傳值為object)。





C#2.0更提供yield return免除自己實作IEnumerator的困擾,
編譯器看到yield return會自動建立IEnumerator類別並回傳IEnumerator型別。



最後一樣可巡覽集合類別。


2017年4月4日 星期二

[C#] 使用繼承與調用基底類別建構子與使用new隱藏的注意事項

說明:
建立一Engineer類別繼承一抽象類別Employee(範本模式)。




當Engineer調用Employee的建構子時, 程式的執行順序會是先進入Employee建構子的區塊,再進入Engineer的建構子。


使用new隱藏修飾子,多型建立instance,會執行基底類別的同名方法,如sbc.GetSalary()會執行Employee的GetSalary方法。

2017年2月28日 星期二

[C#/Modbus] 使用NModbus4讀取Modbus slave的數值(float)

說明:
讀取Modbus slave的input register,1個register為2 bytes,
因此要得到一個float數值,需2個registers。
而Modbus資料排列為big-endian格式,需轉換為little-endian以得到正確數值。




另IEEE-754下float有效位數為7-8位,若寫入slave數值超過有效位數,會造成誤差,
而C#的float有效數值為7位。


參考資料:
https://www.h-schmidt.net/FloatConverter/IEEE754.html
http://ftp.icpdas.com.tw/pub/cd/8000cd/napdos/modbus/nmodbus/nmodbus_api_manual_v1.2_cht.pdf
https://www.mesta-automation.com/modbus-with-c-sharp-libraries-examples/

2017年2月7日 星期二

[.Net/C#] Multi-Thread使用lock造成Deadlock的狀況

使用多執行緒時,常會使用lock,防止不同執行緒對共享參數存取造成非預期的結果。
如:
設備開關控制,thread A要對設備送出open指令,
此時thread B啟動,要對設備送出close指令,
但thread B先執行完畢,最後設備仍然是open的。

因此,可使用lock對設備狀態進行鎖定,使執行緒同步化,
但使用lock可能因兩個thread互相等待造成Deadlock。
如:
worker thread異動資料後,觸發事件後,由UI thread取得該資料來顯示,
就造成thread互相等待而死結。


另外,lock也需針對個別變數使用不同的object,避免單核心CPU進行context switch後造成死結情形。

2016年12月12日 星期一

[C#] 使用EventHandler<T>簡化事件的撰寫

說明:
傳統自行撰寫事件,需先定義委派,使用EventHanler<T>本身就是委派,又加入泛型(傳入事件資料的型別),使得定義方法簽章更為方便。


實作:








2016年11月16日 星期三

[.NET/Tool] Common.Logging與Log4Net的差異與使用

問題:
專案中會看到同時參考Common.Logging與Log4Net,Log4Net就可以輸出Log了,為何還需要Common.Logging?


說明:
專案是可以互相參考的,專案A使用Log4Net輸出log,專案B卻使用NLog,造成管理的不便,
此時使用Common.Logging可提供抽象,由Log4net等dll來實作這些方法,
可以整合Log4net或NLog等.NET常見的Log函式庫,讓專案間可以使用Common.Logging來當Interface。

使用NuGet加入Common.Logging後,using與建立log物件,如下圖:
在app.config加入Logging Configuration後(使用ConsoleOutLoggerFactoryAdapter),
即可輸出Console。



搭配Log4Net,使用NuGet加入Common.Logging.Log4Net1215(目前最新),NuGet就會自動加入對應的Log4Net版本1.2.15(package version為2.0.5),
一樣需設定Logging Configuration,即可輸出Console。




Logging Configuration需注意的是:
● factoryAdapter內的type屬性,最後的Common.Logging.Log4Net1215版本號需正確。
● factoryAdapter下的ConfigType屬性設為INLINE表示讀取專案app.config內設定,若沒設定該屬性,則須有外部設定檔。

輸出外部log,可使用RollingFileAppender

附上Log4Net版本號與NuGet package version對應,如1.2.15對應NuGet 2.0.5。


參考資料:
http://netcommon.sourceforge.net/docs/2.1.0/reference/html/ch01.html
http://logging.apache.org/log4net/release/config-examples.html
https://cmatskas.com/extend-the-common-logging-api-with-log4net/
https://github.com/net-commons/common-logging/wiki/Common.Logging-Packaging-and-Versions
http://stackoverflow.com/questions/37171988/nuget-package-version-not-matching-reference-version