星期三, 7月 29, 2009

轉個想法..讓架構變簡單..

今天有人問我, 他在寫程式時遇到一個問題, 就是他有一個父類別Product, 有一些子類別 a..b..c..像下圖這樣..

image

他跟我說因為產品常常在新增, 每多一項就要多一個 class 去增加代表新產品, 他說他快瘋了, 問我有沒有辦法不要動到這一堆的class 我看了一下他的 class,仔細看..他的子 class 都只是簡單的 field 還有實做 products 的 method 而已, 這樣的 class 效用其實不大, 我給他的建議是, 改成只有一個class, 然後之前那些子 class 的 field 就直接用 dictionary 去處理..

image

public class products
{
public int ID;
public string name;
public Dictionary<string, string> PropertyDic = new Dictionary<string, string>();

public string GetAllInfo()
{
string info = string.Join(",", PropertyDic.Select(a => a.Value).ToArray());
return ID + " " + name + " " + info;
}

public void AddProperty(string key, string value)
{
if (PropertyDic.ContainsKey(key))
PropertyDic[key] = value;
else
PropertyDic.Add(key, value);
}
public void RemoveProperty(string key)
{
if (PropertyDic.ContainsKey(key))
PropertyDic.Remove(key);
}
}

這樣以後新增一個產品就不用再去新增一個 class 了..程式也變簡單好改了..Party..

星期四, 7月 23, 2009

如何在 foreach 刪除 collection

之前在寫程式時, 遇到一個問題, 就是在foreach裡修改collection, 看code吧..

List<int> intLi = new List<int>();
intLi.Add(1);
intLi.Add(2);
intLi.Add(3);
intLi.Add(4);
intLi.Add(5);

foreach (int i in intLi)
{
if (i.Equals(2))
intLi.Remove(i);
}

這會引發一個Exception..

集合已修改; 列舉作業可能尚未執行。

我一開始的解決方法是..

List<int> intLi = new List<int>();
intLi.Add(1);
intLi.Add(2);
intLi.Add(3);
intLi.Add(4);
intLi.Add(5);

List<int> listTemp = new List<int>();
foreach (int i in intLi)
{
if (i.Equals(2))
listTemp.Add(i);
}

foreach (int i in listTemp)
{
intLi.Remove(i);
}

可是看起來感覺很遜..Confused..google一下..別人提供的方法好多了..Thumbs-up..

List<int> intLi = new List<int>();
intLi.Add(1);
intLi.Add(2);
intLi.Add(3);
intLi.Add(4);
intLi.Add(5);

for (int i = intLi.Count - 1; i >= 0; i--)
{
if (intLi[i].Equals(2))
intLi.Remove(i);
}

如果有人有更好的方法..歡迎提供阿..Vampire BatVampire BatVampire BatVampire BatVampire BatVampire BatVampire Bat..

星期三, 7月 15, 2009

使用 Entity Framework 新增 child entity 免 parent object

今天要來紀錄一下有關 Entity Framework 效能的小技巧, 話說..我們在新增 relationship table 的資料時, 我們會這樣寫..

image

using (EF.Entities db = new EF.Entities())
{
EF.TableA ta = db.TableA.Where(a => a.ID == 10).First();
EF.TableB eb = new EF.TableB();
eb.TableA = ta;
eb.TableA.TableName = "testB";
db.AddToTableB(eb);
db.SaveChanges();
}

可是仔細看看..這一段code..這會先丟出一個select的tsql去資料庫抓取資料..把資料抓回來後..才去做更新..這樣好像有點脫褲子放屁..對效能也是有點影響的..所以..有另一種方法..不用先select..直接更新就行了..看codeㄅ..

using (EF.Entities db = new EF.Entities())
{
EF.TableB eb = new EF.TableB();
eb.TableA.EntityKey = new EntityKey("Entities.TableA", "ID", 10);
eb.TableA.TableName = "testB";
db.AddToTableB(eb);
db.SaveChanges();
}

這樣就很直接去新增..不會在多繞一圈啦..BugBugBugBugBugBug..不過個人還是喜歡用第一個啦..有 IntellSence 的感覺換取一點點效能..ok低啦..

參考:

星期四, 7月 09, 2009

解決 Entity framework 對於 SQL 欄位的預設值

我們平常在設定 SQL 的 Table 時, 會將一些欄位直接用 SQL 的 default 處理掉, 例如 Datetime 會設定 getdate() 等..而在使用 Entity Framework 時我也是使用同一觀念去設計, 不過這裡卻遇到了問題, 就是在新增時會產生出錯誤..

SqlDateTime 溢位。必須在 1/1/1753 12:00:00 AM 和 12/31/9999 11:59:59 PM 之間

奇怪了..我在 SQL 的 datetime 欄位有設定預設值阿, 怎麼會有這錯誤資訊, 查了一下找了一下, 發現問題了..簡單說如果你沒有告訴Entity Framework 你 Datetime 欄位的值, 它就給你插入SqlDateTime.Null, 所以就產生錯誤訊息了, 所以解決的方法就是去手動編輯EDM, 然後在需要使用 SQL 的 default 的欄位修改成下面這樣..

<Property Name="dtInsert" Type="datetime" Nullable="false" StoreGeneratedPattern ="Computed" />

這樣就可以解決問題了..

ps:上面那個屬性要設定在SSDL檔非CSDL..

參考:
http://social.msdn.microsoft.com/Forums/zh-TW/238/thread/192c885f-47c7-4cd1-8cd9-46913333c7eb
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/96b53cf0-2a0a-459d-a26e-52486dc4fb1f/

星期三, 7月 01, 2009

WPF 的 MultiLine

前幾天需要做一個簡單的 WinForm 應用程式, 不過想想現在 .net 4.0 都快出了, 當然用WPF來做啦, 二話不說當然開了新的WPF專案, 把該有的控制項拉一拉, 再把程式補進去, 感覺還是一樣簡單, 不過是事情不"愚人"想的這麼簡單, 馬上就遇到問題, 那就是WPF的TextBox的TextMode 沒有 MultiLine 的屬性, 這下好了..糗了..Confused..不過還好有google..Embarrassed..找到解決方法,只要加入

AcceptsReturn="True" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap"

這些屬性就好了..解決..收工..Vampire Bat..

ps:話說..google感覺沒啥資料可以找..是大家都還沒開使用WPF嗎?..Sick

參考:
http://blogs.oosterkamp.nl/blogs/jowen/archive/2009/05/04/multiline-textbox-in-wpf.aspx