文章出處

我一直想把EntityFramework(簡稱EF)的那一套搬過來,應用于HTML5 SQLite。 幸運的是,我幾乎做到了,有些功能無法完成的那是因為SQLite本身不支持。至少從現在已經完成的功能來看,我們幾乎可以像EF那樣去操作數據庫。

 

在我們這個框架中,所有對數據庫的訪問都封裝在了命名空間"nova.data"下面。其下主要包括了以下類:

  • nova.data.DbContext
  • nova.data.Entity
  • nova.data.Repository
  • nova.data.Queryable

 

下面我將逐一詳細闡述。

 

4.1 nova.data.DbContext

這個類相當于是數據庫的定義。我們定義的數據庫的類都應該繼承自這個類。下面讓我們先來看個例子吧。

 

 

這段代碼定義了一個數據庫,但實際上里面只有一張表,關于表的定義我會在下一節中詳述。這里唯一的一張表就是"this.targets", 類型是"nova.data.Repository",相當于EF中的DbSet,實現的都是倉儲模式。

 

請注意上面的第6行代碼,nova.data.DbContext構造函數的第2個參數是版本號(字符串)。這個版本號的神奇之處在于,當它改變的時候,那么在初始化數據庫的時候(通常在index.html),整個數據庫就會重新創建。如果你希望數據庫在重新創建的時候能夠帶一些初始數據,那么你可以覆寫initData方法。

 

讓我們把目光再次投向第10行代碼。上面我說了,這一行代碼是在這個數據庫中定義了一張表。如果還想添加更多的表怎么辦呢?對于聰明的你來講一定不成問題。只需要在這個at.domain.AtDbContext下增加一些屬性,并且這些屬性的類型都是nova.data.Repository。值得一提的是,repository的第一個參數是一個構造函數,并且類型必須繼承自nova.data.Entity。具體的關于repository個entity的定義,我會在后面的內容中詳細闡述。這里你只需知道如何定義一個數據庫,如何往數據庫中添加/刪除/更新表。

 

4.2 nova.data.Repository

這個類相當于EF中的DbSet,跟nova.data.DbContext一起實現了倉儲模式。所謂倉儲模式,就是說任何對repository的增加/刪除/更新操作都只有在調用了DbContext.saveChanges之后才會生效。我們這個框架中提供的數據訪問也是這樣一種模式,如此你便可以同時提交多條數據更改了,而不是每一次更改都要調用一次數據庫。

 

這個類相當于EF中的DbSet,主要用于定義表。其第一個參數是實體類的構造函數,實體類需繼承自nova.data.Entity, 第2個參數是字符串,及數據庫中表的名字。

 

這個類下面有很多方法,我就不一一贅述了。發個截圖吧,相信從方法的定義大概看得出是做什么的:

 

這個類實際我一直想著改造下的,那就是讓它繼承自nova.data.Queryable. 不過現在這樣用著也滿足需求,也挺方便。

 

這個類有個已知的BUG,會在本章末尾闡述。

 

4.3 nova.data.Entity

我在設計這個類的時候,我也試著模仿EF中的CodeFirst模式的代碼。就是說每一個字段的數據類型在定義這個實體類的代碼中體現,幸運的是我幾乎實現了這樣的功能。只要你在定義實體類的時候,給每一個屬性指定一個初始值,那么在創建數據庫的時候,就會根據這個初始值來指定數據類型。目前支持的數據類型有:integer, decimal,string, date,boolean。如下面的代碼:

 

 

在我們的框架下開發應用程序,所有的本地數據庫實體類都應該繼承nova.data.Entity。

 

這個類只有一個屬性integer id,這也是SQLite數據庫每一張表默認都會帶的字段。因此,在你的數據庫實體類的定義中,不應該再定義id這個字段了。除了這個id屬性,這個基類還定義了一些方法,主要是用于處理數據類型的。

 

這個類的另一個強大之處在于,以Target實體類為例,當你同時往數據庫插入了多條target記錄,并調用了dbContext.saveChanges方法時,每一個target的id會得到更新。這個特性也是模仿EF的,因為我們在使用EF的過程中發現這個特性實在太有用了。相信你在使用我們框架的過程中也會喜歡這個特性的。

 

4.4 nova.data.Queryable

這個類是模仿Linq中的IQueryable的,其工作原理也是和IQueryable類似。請看下面這行代碼:

db.targets.where(“price >= 10”).where(“price < 20”).orderBy(“category”).thenBy(“name”).toArray(callback).

 

如果你熟悉Linq,那么這行代碼你一定不會陌生。是的,我們的框架就實現了這樣的功能。上面這行代碼,在調用toArray之前,每一個查詢/排序條件都沒有提交到數據庫,而是放在了內存當中,只有當調用了toArray時,才會執行數據庫的查詢。

 

請注意上面這行代碼的第一個where,這個where方法實際上是repository中定義的,但返回的卻是queryable,而后面的where和orderBy等都是queryable的實例方法。這正是模仿Linq設計的巧妙之處。

 

這個類的其他方法都比較一目了然了,就貼個截圖吧:

 

 

4.5 常用例子

前面我把我們框架中對于本地數據庫訪問的每一個成員都做了詳細的介紹,但如果你對JS面相對象或者EF不那么熟悉的話,可能還是看得有些云里霧里。好吧,下面我就貼一些常用的例子,相信這些例子一定能讓你領略到這個框架的獨特魅力。

 

4.5.1 定義數據庫

先上代碼:

 

這段代碼只定義了一個targets表,你當然可以增加更多的表,只需要把第3行代碼復制幾份,然后改改名字就可以了。

 

4.5.2 定義實體類

先上代碼:

 

這里定義了一個Target類,還有很多個實例方法,看上去跟普通的類沒有什么區別,唯一的區別就是繼承自nova.data.Entity.

 

 

4.5.3 查詢

 

 

4.5.4 插入

 

 

4.5.5 更新

 

4.5.6 刪除

 

4.6 已知問題

目前有1個問題無法解決。

 

當同時執行批量插入、批量更新、批量刪除的時候會報錯。因此,如果你想同時執行這些批量操作的話,那么應該讓一種批量操作完成之后再執行另一個批量操作。

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


全站熱搜
創作者介紹
創作者 大師兄 的頭像
大師兄

IT工程師數位筆記本

大師兄 發表在 痞客邦 留言(0) 人氣()