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