2013/08/17

如何在關掉SqlDataReader時也關掉SqlConnection

在C#中以ADO.NET連接資料庫,遇到一個應用是method A去呼叫method B,B開啟一個SqlConnection物件後,執行select statement,將獲得的SqlDataReader傳回給A使用。

在method A中使用SqlDataReader後,可以將SqlDataReader關閉(close),來加速回收此物件的速度。可是,在method B中的SqlConnection就沒有辦法做close了。

當然我們不能在離開B時就把SqlConnection就close掉,因為在method B中執行SqlCommand.ExecuteReader時,並不是一次就把所有的result set都放進SqlDataReader中,而是以stream的方式透過SqlConnection傳進來。所以如果先把SqlConnection關了,SqlDataReader也就讀不到資料了。若是SqlConnection不關閉,又會在一段時間中佔用database connection與相關資源。

後來在網路上找到了這一篇
http://codes.codedigest.com/CodeDigest/164-Implicitly-Closing-the-Connection-object-when-SqlDataReader-is-returned-from-a-Function.aspx

特別注意到這一行
SqlDataReader myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);

如果在ExecuteReader加入參數CommandBehavior.CloseConnection,則當對SqlDataReader進行close時,也會將其底層的SqlConnection也關掉。這樣,就可以適時地把SqlConnection關閉,儘早釋放出資源。這對尤其是server-side的系統來說,相當重要。

2013/08/13

在Chrome中,iframe中呼叫parent function的問題

在開HTML發網頁時,Page A以iframe的方式包含了Page B,而B則會下列方式呼叫A的function。
parent.test('abc');

當執行到這行呼叫時,chrome會丟出錯誤
Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match.

一直無法瞭解這錯誤的成因,也不知怎麼解決。
但後來發現,如果把Page A, B放進server (如Tomcat),瀏覽器是以http://的方式去執行,就可以正常作業;而原來是以瀏覽器直接開檔案的方式來測 (用file://),就會有前述的問題。

嗯...這個問題花了我5小時...

2013/08/08

Drools Expert 6.0 beta 試玩

前言
最近可能會接觸expert system,經過一些study,焦點放在三個
參考了一些評比
  • http://illation.com/banking-benchmark-performance-jess-vs-drools/
  • http://www.integratingstuff.com/2010/07/18/rule-engines-in-java-jboss-drools/
由於Drools是open source,且效能並不遜於其他兩個商業軟體,所以就先從Drools開始玩起了

下載與安裝
Drools的下載頁 http://www.jboss.org/drools/downloads
由於目標是在Drools Expert上,依據description的描述,就下載Drools。我下載的是6.0.0 beta 5,大小約114M。6.0版與前版之差別可以參考這裡。解開壓縮檔後,裡面包含開發所需要的jar files, 還有原始碼、javadoc、參考文件與範例等。
如果要安裝eclipse的plug-in,

  1. 參考http://docs.jboss.org/drools/release/5.5.0.Final/droolsjbpm-introduction-docs/html_single/index.html#d0e95,先以2.1.3.1方式安裝GEF
  2. 安裝Drools plug-in:以eclipse的 Help | Install New Software,在Location輸入 http://download.jboss.org/drools/release/6.0.0.Beta5/org.drools.updatesite 來進行安裝。(或是先用瀏覽器到http://download.jboss.org/drools/release去尋找相對應的版本目錄)
  3. 在 http://www.jboss.org/drools/downloads.html 下載  Drools and jBPM tools,解壓縮至硬碟
  4. 再以1.中文件 2.1.3.4 所述方法,設定 drools runtime
程式開發
接下來我們來進行程式的開發。先在eclipse中建立新的專案,記得在專案的properties之Java Build Path裡,新增一個library,把上圖中binaries下所有的jar files都加進來。

首先我們來撰寫rule的部份:
colorRule.drl 

rule "red"
when
color:Color(color=='red')
then
System.out.println("#ff0000");
end

rule "green"
when
color:Color(color=='green')
then
System.out.println("#00ff00");
end

rule "blue"
when
color:Color(color=='blue')
then
System.out.println("#0000ff");
end
這裡我們定義了三個rule,讓三種顏色的名稱對應到其color code。

接下來Java來開發程式。首先需要一個entity object

Color.java

public class Color {
private String color;

public Color(){}
public Color(String color) {
this.color = color;
}

public String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}
}
然後再一個帶有main()的可執行程式
DrColor.java

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

import org.drools.compiler.compiler.DroolsError;
import org.drools.compiler.compiler.DroolsParserException;
import org.drools.compiler.compiler.PackageBuilder;
import org.drools.compiler.compiler.PackageBuilderErrors;
import org.drools.core.RuleBase;
import org.drools.core.RuleBaseFactory;
import org.drools.core.StatefulSession;


public class DrColor {
private RuleBase rbase = RuleBaseFactory.newRuleBase();
private PackageBuilder pbuilder = new PackageBuilder();
private String DRL_FILE = "colorRule.drl";

private void initDrools() {
// read DRL file and add to package builder
try {
Reader reader = new InputStreamReader(DrColor.class.getResourceAsStream(DRL_FILE));
pbuilder.addPackageFromDrl(reader);
} catch (DroolsParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

PackageBuilderErrors errors = pbuilder.getErrors();
if (errors.getErrors().length > 0) {
System.out.println("ERROR:");
for (DroolsError err: errors.getErrors()) {
System.out.println(err);
}
throw new IllegalArgumentException("Could not parse knowledge");
}

// add package to rule base
rbase.addPackage(pbuilder.getPackage());
}

private void determineColor(String col) {
Color c = new Color(col);
StatefulSession session = rbase.newStatefulSession();
session.insert(c);
session.fireAllRules();
}

public static void main(String[] args) {
DrColor m = new DrColor();
m.initDrools();
m.determineColor("blue");
m.determineColor("red");
}
}

當執行時,若能看到#0000ff與#ff0000,就表示Drools Expert可以正常執行了。
接下來,就要由你來發揮想像力,讓這專家系統發揮效力了。

參考文件:
Drools Expert User Guide 6.0 beta
Drools Documents

2013/07/22

the type or namespace name "xxxxxxxxxx" could not be found

[PROBLEM]
在Visual C# 2010,有project B的程式中使用到project A的class AA。AA有設為public,且project B的reference也有加A。
Design time時,在B的程式中用到AA,auto-complete都沒問題。
但是要執行時做build,就出現 the type or namespace name "xxxxxxxxxx" could not be found的錯誤

[SOLUTION]
錯誤主要是來自各project的target framework不一致。剛查了一下,project A的target framework是 ".NET Framework 4",而project B的則是 ".NET Framework 4 Client Profile"。
將project B也設為".NET Framework 4"就沒問題了。

target framework要在那裡設?點選你的project後,主選單 Project | xxxxxx Properties,在Application tab中就可以找到了。

2013/07/09

Visual Studio為什麼不會提醒我要加try/catch

最近使用Visual Studio 2010寫些C#的程式,有一點不太習慣的地方是,VS不會要求你那裡要加try/catch (用慣VS的人應該不會覺得不習慣啦,是我這種用過Java的人才這麼感覺吧)
這好處是可以忘了有exception這回事,就暢快的跟著happy path寫下去;可是,人生總是不會如此美好,該出錯的地方一定會出錯的
那開發者就很難去預想run-time時那裡會出錯,就算有心想去加try/catch,也不知道那些method會丟出exception,又會丟出那個exception class (除非去翻文件,可是,這不是IDE應該幫PG減輕負擔的地方嗎?)
結果,就加了一堆都是catch Exception的code

有Java開發經驗的人,應該會知道method後面會定義要丟那些exception,如:
public void foo() throws IOException, ParseException

在Eclipse, NetBeans等這些免費的tools裡寫程式,IDE總會提醒你那個method會丟出exception,你必須加try/catch或是在目前的method中加上throws。

一直在想,為什麼Java的工具可以做得到,Visual Studio卻沒這功能,而且VS經過這麼多代了,難道VS的users都不用這些功能?或是不抱怨VS沒有這樣的功能?
查了一下,確實還有些users在抱怨,可是...就是做不到

後來研讀了一下,推測了VS為什麼沒有這樣的功能 (對.NET我還不是很熟,所以有說錯敬請見諒,也請指教)

因為像在C#裡method的定義,並沒有像Java的throws的宣告
在Java的工具中要做到這樣的功能很容易,tool只要去查你叫用methods的宣告,就可以知到這些methods有沒有丟exceptions,丟怎樣的exceptions,然後再提醒PG要處理,但是.NET中method並沒有這樣的宣告,如果VS要做到這樣的結果,就必須去scan所有使用到的methods的內容,然後一層一層往上追上去,即使已經翻成MSIL的library也必須要去追

Java只要追你叫用到的那些methods的宣告;.NET則要追你叫用到的那些methods的內容,還有他的祖宗八代、親戚五十等等所有相關到的內容

這也可以體諒為什麼VS/.NET不提供這樣的功能了,實在是做不到 (應該說很難做到,如果要做,用VS寫程式應該會lag蠻嚴重的)

所以,用VS寫程式,就先當個happy PG吧
exception,等被丟出來再說吧