C#自動實作屬性


在 C# 3.0版本開始提供超好用的自動實作屬性,以前宣告private變數的方式都免了~落落長的寫法丟光光,
只要{get; set;}一行,編譯器就會幫我們用private匿名支援欄位做掉!
如何一行搞定~請參考自動實作的屬性

但是但是...千萬要小心,不要{get; set;}用很爽~結果外部的程式竟然能修改你的物件就糟糕了
所以請參考使用自動實作的屬性來實作輕量型類別

以上記錄一下,以後方便自己翻閱

Left Join in LINQ

在SQL使用Join可大致分為Inner Join、Outer Join,其中Outer包含Left、Right、Full有的沒的。
今天記錄一下在LINQ(搭配C#)中如何做到Left Join的效果~

假設有2個table"Customer"&"Product"分別記錄顧客與產品資訊,假設這2個table可透過Name、Address欄位串接,最常用的Inner Join寫法如下:
//JOIN 1(Inner):如果customer沒有joinproduct就不保留
var result = customer.Join(product, c => new { c.Name, c.Address }, p => new { p.Name, p.Address }, (c, p) => new { c, p }).ToList();
產出的結果是擁有Product的Customer才會被保留,比如說王小明留下了客戶資料卻沒有訂購任何產品,那麼Join出來的new table是不會有王小明的資訊。

如果要以Customer為基準,無論有無訂購產品皆保留顧客資訊,那麼就要以Customer為Left Table作Left Join,寫法如下:
//JOIN 2(Outer-Left Join):即使customer沒有對應的product,也保留
var result = (from c in customer
join p in product
on new { c.Name, c.Address } equals new { p.Name, p.Address } into newProduct
from newP in newProduct.DefaultIfEmpty()
select new { c, newP }).Distinct();

Enumerable.GroupBy

最近要針對某複雜資料結構做分群,問題是資料又來自不同的資料供應者,只好先把資料兜成自定義class再使用Enumerable.GroupBy

MSDN的範例較簡單,key用int,被group的資料則是string

若是自定義class可參考stackoverflow Matt Smith建議的寫法,引述寫法如下:
List<smth> list = new List<smth>();
IEnumerable<IGrouping<int, smth>> groups = list.GroupBy(x => x.id);
IEnumerable<smth> smths = groups.SelectMany(group => group);
List<smth> newList = smths.ToList();

又key不用侷限於int,個人試過用資料中的多組欄位組成unique string來分群組亦可!

Telerik Grid Custom Binding by TelerikMvcGridCustomBindingHelper


Telerik Grid可設置.Sortable()、.Pageable()、.Groupable()、.Filterable()達到排序、分頁、分群、過濾資料的效果,但這是使用Telerik所提供的binding為前提。

若採用CustomBinding,以上效果(排序、分頁、分群、過濾)全部都要自行實作,實作方式請參考官網CustomBinding,或是直接下載官方論壇提供的範例


依官方解法,每次CustomBinding都要針對Binding的資料結構各實作paging、sorting、grouping一次,尤其grouping更要事先設計好針對那些欄位是可以排序的。
若覺得官方解法太麻煩~~是真的很麻煩ε(┬┬_┬┬)3 ,或是資料結構過於複雜無法呈現,或你跟我一樣懶惰XDD
建議可搭配另一套件TelerikMvcGridCustomBindingHelper,達到更彈性、修改更少的寫法!

承接前篇文章Telerik Grid Custom Binding,BL與View都不用做任何改變,針對Controller所需異動描述如下

1. 至CodePlex下載TelerikMvcGridCustomBindingHelper套件
解壓或用NuGet安裝裡面二支library
download:http://tgh.codeplex.com/
library:TelerikMvcGridCustomBindingHelper.dll、TelerikMvcGridCustomBindingHelper.NHibernate.dll
version:1.10.15.247
notice:Telerik要記得更新到2012 Q2

2. 加入AutoMapper參考
download link:使用NuGet下指令安裝,指令為PM> Install-Package AutoMapper 
version:2.1.267.0

3. 把Helper要用到的另二種library下載回來參考
download:http://nhforge.org/Default.aspx
library:NHibernate.dll、Iesi.Collections.dll
version:3.3.1.4000

4. 修改Controller寫法
[GridAction(EnableCustomBinding = true)]
public ActionResult ListPO_CustomBinding(GridCommand command)
{
int totalCount = POService.QueryPOListIndex(command);
ViewBag.POTotalCount = totalCount;
List<PO> data = POService.QueryPOList(command);

//使用TelerikMvcGridCustomBindingHelper
for (int i = 0; i < (command.Page - 1) * command.PageSize; i++)
{
PO dd = new PO();
data.Insert(0, dd);
}
IQueryable<PO>
query = data.AsQueryable();
var gridHelper = new GridCustomBindingHelper<PO, PO>(command, query);
var gridModel = gridHelper.BuildGridModel();
gridModel.Total = ViewBag.POTotalCount;
return View(gridModel);

}


仔細比較與前篇寫法的差異處(黃色highlight),只要修改Controller一點點就省去實作N遍的paging、sorting、grouping
真是太感謝TelerikMvcGridCustomBindingHelper的開發團隊╭ (′▽`)╭(′▽`)╭(′▽`)╯

P&P義法創意廚房

這年頭一堆簡餐店普普通通也要收我二三百塊,尤其義大利麵更是飆到三百多要四百。

不過超平價義大利麵─艾隆、Mint就另當別論,這二家都是走好吃又吃得飽,但不還算是中階的精緻餐廳。
P&P義法創意廚房算是用餐環境不錯,料理品質有一定水準的餐廳,重點是他不貴!!加了10趴服務費也可以壓在300大洋以內,揪感心ㄟ

當然,愛吃美食的人也可以加點套餐~
P&P的套餐不馬虎,這次+99的四選三,三樣都頗滿意說


當天例湯是番茄牛肉清湯,不吃牛的朋友可在加點套餐前先詢問當日供應為何。
湯不錯喝,還能吃到二小塊牛腩,可惜有點小碗XDD


手工麵包附鮪魚沾醬,鮪魚很香沒腥味,也沒有打得過細~有吃的到鮪魚肉的口感


冰咖啡雖不能續杯,但飲料容量誠意十足,不怕一口喝掉就沒有XD

甜點選擇頗多,為了避開其他友人選的起司蛋糕,原以為是最普通的一款,沒想到美味之餘,蛋糕上層的特殊餅皮(?)還蠻特別的,冰冰的起司蛋糕沾點微酸的果醬真不錯吃!


義大利麵的部分擺盤、口味都不錯,不過友人說份量的拿捏似乎沒有很精準,有的人超大盤,有的人小小一坨?!

這次聚餐重點是喇賽(聊天),很忙亂的分食秀就免了,只針對自己點的深海辣味墨魚麵說說~
首先,用料部分夠大方,三隻蝦、五六個透抽和一個淡菜,NTD 230真的很經濟實惠,而且墨魚麵通常都比較貴說...為什麼一直繞著價錢打轉,很窮嗎╮(▔▽▔")╭

蝦子有先剝殼,透抽也處理的QQ不會老,除了吃完會牙齒黑黑,這道深海辣味墨魚麵帶著點點辣味和海鮮香,是很涮嘴的義麵。然後麵的硬度也是我愛的,但牙口不好?或喜愛稍軟口感的朋友最好請廚師調整,P&P的麵真的比較硬唷。
但是但是~麵好乾好乾好乾!!!要是墨魚source像其他友人一樣可以多些就好(只有我點墨魚,不知道是不是這家墨魚都乾巴巴)
深海辣味墨魚麵(NTD 230)



★P&P義法創意廚房(西門店)
addr:台北市成都路50號2樓
phone:02-23818980

<科教館Go好玩>飛閱臺灣,飛越台灣

早在去年就從中廣蘭萱時間得知齊柏林籌畫空拍台灣,那時一直期待電影<域忘>的上映,沒想到2013上映前還有個綠動地球●飛閱台灣特展。

可惜錯過2012台北電影節的觀賞機會,趁國立台灣科學教育館這波展覽,一定要先來震撼一下!


展覽以各項小主題為畫分,每面牆都有一個特色一個故事,像是一入場的阿朗壹古道便是近年炒得沸沸揚揚的環保議題,另外再從山(Moutain)、河(River)的角度去看台灣產業是如何對待自己的家園,在人們愛護地球的意識抬頭後又是怎麼作努力。

看到滿目瘡痍的山。。。


會很懷念原始、應有的面貌。。。


帶小朋友親近觀察自然也是一種守護方式~


透過齊柏林的鏡頭,每段鳥目台灣都是關懷母親台灣的一種角度,即使你是後段班出生的台灣囝仔,都能藉由短短幾分鐘的影片一窺環境的變化。


看了許多環境遭到破壞的高空照片,心情蠻差的T_T  但也要感謝齊柏林先生、台達電、阿布電影公司所付出的心力,讓我們正視自己土地上的變化~~美麗海岸線離我們越來越遠,蔥鬱的山林頂上無毛,希望我們傳給下一代手上的寶島依舊是物種豐富、人與大自然和諧相處的寶地。

謝謝你,齊柏林攝影師


以下僅列幾張圖片,更精采的資訊還要各位踴躍支持綠動地球●飛閱台灣特展,展覽開放到2012.11.30唷 0 .<

像墨水一樣的河流

我們先不愛惜山林,山林才不愛惜我們 …(⊙_⊙;)… 
讓自己有個機會親近這塊土地,撥個時間去科教館看看吧



★飛閱台灣●綠動地球(國立台灣科學教育館)
addr:台北市士商路一八九號
phone:02-66101234 # 1000、1005 
opening hours:9am-5pm(Mon.-Fri.)、9am-6pm(Sat.-Sun.)
           本展展期至2012年11月30日

C# / JS 無條件進位

用.NET寫Web就是用C#(或VB)和JavaScript,記錄一下數字的無條件進位寫法~

C#
Math.Ceiling(1.4) = 2 ;
JavaScript
Math.ceil(1.4) = 2 ;

Telerik Grid Custom Binding

Telerik Grid算是做得很完善,API也多~但客製化需求還是在所難免。
比如有個表單系統只提供最簡單的資料瀏覽,姑且不論是否下查詢條件,要是資料百萬筆豈不是起肖?!

較好的做法是用分頁區別之餘,但每次只取該分頁的資料,而不是一次取回百萬筆資料再作分頁

本文就要來介紹,如何實作Custom Binding

1. 計算總筆數(因為是CustomBinding,GridModel需要的總筆數必須自己計算)
public int QueryPOListIndex(GridCommand command)
{
var entity = mydata.PO.AsQueryable();
int ttlCount = entity.ToList().Count();
return ttlCount;
}


2. 像平常一樣取資料(請依照自己的需求和資料作變化)
public List<PO> QueryPOList(GridCommand command)
{
var entity = mydata.PO.AsQueryable();
//Sorting(必須有Default的Order By條件,否則會Error)
entity = entity.OrderBy(order => order.PONo);
//Then paging
if (command.PageSize > 0)
entity = entity.Skip((command.Page - 1) * command.PageSize);
entity = entity.Take(command.PageSize);
return entity.ToList();
}


前面二項為Bussiness Layer(POService),若專案架構較小~亦可將其寫在Controller中
3. Controller
//須注意的是, ViewBag.DataTotalCount在此頁載入時須先給予一預設值(ex:0),之後的查詢function再賦予正確值
public ActionResult ListPO()
{
ViewBag.POTotalCount = 0;
return View();
}

[GridAction(EnableCustomBinding = true)]
public ActionResult ListPO_CustomBinding(GridCommand command)
{
int totalCount = POService.QueryPOListIndex(command);
ViewBag.POTotalCount = totalCount;
List<POt> data = POService.QueryPOList(command);
return View(new GridModel
{
Data = data,
Total = totalCount
});
}


4. View
@(Html.Telerik().Grid<PO>()
.Name("Grid")
.Columns(columns => {
columns.Bound(c => c.PONo);
columns.Bound(c => c.DocDate);
columns.Bound(c => c.Company);
columns.Bound(c => c.Vendor);
columns.Bound(c => c.Status);
columns.Bound(c => c.CmpltReceived);
})
.Pageable(settings => settings.Total((int)ViewBag.POTotalCount))
.DataBinding(dataBinding => dataBinding.Ajax().Select("ListPO_CustomBinding", "Inbound"))
.EnableCustomBinding(true)

.Sortable()
.Groupable()
)