上一節我們開始內容管理的數據設計,這節我們來完成內容管理BAL部分的代碼。
在實現Category的時候,增刪改的SQL語句基本上就是一段特定格式的字符串,雖然可以自己做ORM工具來自動生成,但不是我們這個教程要講的。我們今天重點講下對查詢後結果的優化。
在Model.Categoty類中,我們數據轉換代碼是這樣的:
事實上上面的代碼是不夠安全的,比如:
model.Id = int.Parse(result["Id"].ToString());
result中未必包含Id的鍵值,結果就可能為空,轉換時就會出錯;
result中包含Id的鍵值,但可能不是數字,轉換時也會出錯;
一旦出錯,程序就爆掉了。
正確的代碼應該加上上面兩種情況的判斷,外加調用int.TryParse的方法, 嘗試去轉換,但是這就不是一兩行代碼就能搞定的了,一個欄位的處理可能就要4-5行。如果僅僅是Category還好,欄位不多,Content有12個欄位,還有DateTime這種類型,幾十行代碼來處理這些就顯得過於臃腫了,所以我們需要進行代碼優化。
上面的代碼,共同之處都是從一個Hashtable的實例中獲取數據,不同的地方有兩點:一是返回類型,二是鍵值,有共性就可以用函數,有不同就傳參數,外加C#的一個專門用於工具類的擴展方法,就可以完美解決此問題。
在BAL中我聲明了一個靜態類BALTools,定義了對應Sqlite四種基本類型的函數:
namespace Diary.BAL
{
static public class BALTools
{
static public string toString(this Hashtable ht, string key, string dv = "")
{
if (ht == null) return dv;
if (!ht.Contains(key)) return dv;
if (ht[key] == null) return dv;
return ht[key].ToString();
}
static public int toInt(this Hashtable ht, string key, int dv=0)
{
string str_v = ht.toString(key);
if (string.IsNullOrEmpty(str_v)) return dv;
int.TryParse(str_v, out dv);
return dv;
}
static public DateTime toDateTime(this Hashtable ht, string key)
{
DateTime dv = DateTime.MinValue;
string str_v = ht.toString(key);
if (string.IsNullOrEmpty(str_v)) return dv;
DateTime.TryParse(str_v, out dv);
return dv;
}
static public bool toBool(this Hashtable ht, string key, bool dv = false)
{
string str_v = ht.toString(key);
if (string.IsNullOrEmpty(str_v)) return dv;
return str_v == "1";
}
}
}
這裡有兩個知識點:
第一個知識點擴展方法。大家可能注意到了,每個函數的第一個參數:this+參數類型+參數名。這種在靜態類、靜態函數中,且第一個參數使用了this,編譯器就會為這個指定的參數類型創造出一個擴展方法。相當於你繼承了這個類,可以使用這些方法。
說起來可能比較難理解,看下動圖就很容易理解了:
我們可以看到,一個Hashtable的實例result,直接擁有了toInt、toString等方法,這種就叫擴展方法,設計好了就可以讓你節省大量重複性的代碼。
第二個知識點是在函數參數中加默認值。比如toString的最後一個參數是
string dv = ""
dv就是default value的縮寫,假設我在取值的這個鍵值不存在,那麼我就事先預設一個值,如果不存在,我就用這個預先設置的值來返回。在函數定義的時候設置了一個值是什麼意思呢?就是調用函數的時候我可以不指定這個值,默認使用函數定義的,只有在有必要更改這個默認值的時候,我才需要指定它。
result.toString(「Name」)
result.toString(「Name」, 「無標題」)
都是可以的。
做完上述的改進,我們開始編碼:
Category的查詢部分:
Content的查詢部分:
通過我們的優化,查詢部分代碼的健壯性、可讀性都得到了很大的提升,而且以後再有其他的資料庫我們也都可以復用這幾個方法,這個工作非常值得。我們無論是做項目還是做產品,其實都要不斷地總結、優化,最終形成你自己的代碼庫,設計更加合理,編碼更加高效。其實這也是我極力向大家推薦C#的原因之一,通過你的長期積累,能做的事情就越來越多,用C#是可以全棧開發的,也就是說,等你積累到了一定程度,你基本上可以優雅、高效的做任何你想做的事了,而且自己寫的類庫根本不用擔心版權問題,這是其他很多語言無可比擬的。
我在教程里的內容都沒有用其他的類庫,然後有些人就各種噴,其實我現在寫這個系列教程就跟打網遊的開荒一樣,一切從零開始。噴子們開發只會用輪子,而我們這些獨立開發者是可以自己造輪子的。
DAL.Content的增刪改函數就沒什麼知識點可說的了,大家自行到Git上查閱代碼。
底層工作準備好之後,我們下一節開始界面設計。
----------------------------------------------------
本教程儘量保證2天一更,項目源碼已作為開源項目加入到Gitee,代碼內容會隨教程實時更新,大家有興趣的話可以關注我,以獲得最及時的更新。私信:
私人日記 可以獲取Gitee的連結;
sqlitestudio 可以獲取sqlitestudio的連結;
菜鳥 可以獲取菜鳥教程連結;
大家閱讀過程中有哪些看不懂或未盡興的地方,可以在評論區留言,我會先記下來在後續的教程中找機會再說。
教程有幫助的話請大家幫忙關注、轉發、擴散,能不能開專欄還需要你們的支持!