SubSonic 是集程式碼產生/ Build Provider (asp.net 2.0 的新特性) 於一身的一個非常不錯的資料存取框架。其靈感來自ROR 裡的ActionPack. 非常適合於小型網站的快速開發。
昨天我開始使用這個框架,發現了一個小問題。
我有一個欄位名為Key,在產生一個Select 語句的查詢時sql 報錯。因為Key 是一個關鍵字,而SubSonic 產生的SQL 中對此未作轉義處理。
Debug 時可以取得其產生的SQL 如下:
SELECT TOP 100 PERCENT [cfg_Tips].[Id], [cfg_Tips].[Key], [cfg_Tips].[Descr], [cfg_Tips].[Value], [cfg_Tips]. [Labels] FROM [cfg_Tips] WHERE [cfg_Tips].Key = @Key ORDER BY [Id];
我修改了一下原始碼中的SqlDataProvider.cs 裡的BuildWhere 方法,暫時解決這個問題。
protected static string BuildWhere(Query qry)
{
string where = "";
string whereOperator = " WHERE ";
foreach (Where wWhere in qry.wheres)
{
if (wWhere.ParameterValue != DBNull.Value)
{
where += whereOperator + "[" + wWhere.TableName + "].[" + wWhere.ColumnName + "] " +
Where.GetComparisonOperator(wWhere.Comparison) + " @" + wWhere.ParameterName;
}
else
{
where += whereOperator + "[" + wWhere.TableName + "].[" + wWhere.ColumnName + "] " + Comparison.Is +
" NULL";
}
whereOperator = " AND ";
}
foreach (BetweenAnd between in qry.betweens)
{
where += whereOperator + "[" + between.TableName + "].[" + between.ColumnName + "] BETWEEN @start" +
between.ColumnName + " AND @end" + between.ColumnName;
whereOperator = " AND ";
}
for (int i = qry.wheres.Count - 1; i >= 0; i--)
{
if (qry.wheres[i].ParameterValue == DBNull.Value)
{
qry.wheres.RemoveAt(i);
}
}
return where;
}
我增加的部分在上面程式碼中標註為綠色。
很奇怪,作者對表名加了方括弧,卻沒有加給列名,這樣顯然就不嚴謹了。
這個庫中還有MySqlDataProvider 等類別也有此問題。因為我現在暫時不用MySQL, 就先不去改那些了。
另外有一個體會就是使用開源的第三方類別函式庫時,盡量都用原始碼方式加入專案。否則出錯了調試不進去。
現在,我使用這個框架的方法是利用它的生成類別的那個網頁GenerateAllClasses.aspx 做程式碼生成,然後自己引用進來。雖然比預設的直接生成後在記憶體中編譯運行要麻煩一點,但是這樣便於Debug. 還是很值得的。
posted on 2007-01-22 00:28 木野狐閱讀(62) 評論(4) 編輯收藏引用網摘所屬分類: .NET
評論
# re: SubSonic 的字段名未轉義問題修正2007-01-22 00:47 TerryLee
SubSonic還不錯,號稱是零代碼資料存取層:) 回覆 更多評論
# re: SubSonic 的字段名未轉義問題修正2007-01-22 00:49 木野狐
@TerryLee
呵呵,是的。不過我不敢用它的自動方式,畢竟我覺得自己的控制少。理由就像這篇post 所描述的一樣。
回覆 更多評論
# re: SubSonic 的字段名未轉義問題修正2007-01-22 00:53 TerryLee
@木野狐嗯,沒錯
我只用它寫過一個小Demo:) 回覆 更多評論
# re: SubSonic 的字段名未轉義問題修正2007-01-22 01:02 木野狐另外使用時感覺這個東西的文檔還是少。舉的例子也很簡單。稍微有用一點的用法都靠自己的摸索。
比如這個:
要根據條件加載一個對象,文檔(pdf)中提到可以用
對象.Load(...) 來加載,其中的參數可以是IDataReader, DataRow, DataTable.
我用一個IDataReader 傳進去,結果搞了半天都是出錯。最後調試到框架原始碼裡發現必須在傳遞IDataReader 進去之前,先自己Read 才能成功。例如我寫的這段簡單例子裡用到:
/// <summary>
/// 得到經辦人所在科室的負責人
/// </summary>
/// <param name="staff"></param>
/// <returns></returns>
public static Staff GetManager(Staff staff) {
SubSonic.Query qry = new SubSonic.Query(Staff.Schema.Name);
qry.AddWhere(Staff.Columns.IsFunctionary, true);
qry.AddWhere(Staff.Columns.OfficeId, staff.OfficeId);
Staff manager = new Staff();
IDataReader reader = qry.ExecuteReader();
if (reader.Read())
{
manager.Load(reader);
}
return manager;
}
http://www.cnblogs.com/RChen/archive/2007/01/22/actionpack1.html