現操week6 :File Management & SQLite Database

需求

實現todo表項的增、刪、改、查 70%
利用數據庫保存及恢復應用狀態 15%
學習使用第三方工具查看數據庫內容 5%
拓展:10%
進行圖片的存取,如每個表項的圖片狀態保存5%
在實驗報告中描述LocalFolder RoamingFolder等存儲位置的作用
在實驗報告中描述StringBuilder 的作用5%

整理:
1. 頁面右上角添加搜索框,實現(按Title)查找功能,以彈出消息框的形式返回查詢的信息。查找可以模糊查找,即Title包含了搜索詞即可。輸入*則返回全部。
2. 增刪改同步於數據庫
3. 保存圖片到數據庫

基礎知識

SQLite的使用

每一個database都是一個sqlite3對象;
每一個語句都是一個sqlite3_stmt對象;每個sqlite3_stmt對象有它的生命週期。

Database Connection Handle

typedef struct sqlite3 sqlite3;
Each open SQLite database is represented by a pointer to an instance of the opaque structure named “sqlite3”. It is useful to think of an sqlite3 pointer as an object.
Constructors: sqlite3_open(), sqlite3_open16(), sqlite3_open_v2()
Destructors: sqlite3_close(), sqlite3_close_v2()

Prepared Statement Object

typedef struct sqlite3_stmt sqlite3_stmt;
An instance of this object represents a single SQL statement that has been compiled into binary form and is ready to be evaluated.
Think of each SQL statement as a separate computer program. The original SQL text is source code. A prepared statement object is the compiled object code. All SQL must be converted into a prepared statement before it can be run.
The life-cycle of a prepared statement object usually goes like this:

Create the prepared statement object using sqlite3_prepare_v2().
Bind values to parameters using the sqlite3_bind_*() interfaces.
Run the SQL by calling sqlite3_step() one or more times.
Reset the prepared statement using sqlite3_reset() then go back to step 2. Do this zero or more times.
Destroy the object using sqlite3_finalize().

Constructors: sqlite3_prepare(), sqlite3_prepare16(), sqlite3_prepare16_v2(), sqlite3_prepare_v2()
Destructor: sqlite3_finalize()

使用UWP時SQLite保存在本地的位置

說了半天使用SQLite開發,那麼我們創建出來的數據庫究竟在存放在哪裏呢?系統默認是放在這個路徑的:C:\Users(username)\AppData\Local\Packages(packagename)\LocalState,其中username當然就不用小編解釋了,當然就是您的用戶名嘍!packagename可以在工程目錄裏面的Package.appxmanifest文件裏查看

常用uri前綴

這裏寫圖片描述

實驗過程

1.畫圖

由於對Layout不熟悉,畫圖都花了好久。。

2. 建立一個DbManager類

拿來主義地使用課件上的代碼即可。
在編寫返回多個結果的search函數時稍微遇到點小問題,查得

The result code SQLiteResult.DONE means sqlite3_step() has finished executing. **In your code snippet, if your data table still have rows need to read, statement.Step() will return SQLiteResult.ROW **result code, which means sqlite3_step() has another row ready to read, not finished.

此外再稍微修改TodoItem,增加一個可寫入Id的構造器。

3. 爲應用程序添加Dbmanager的服務

上週做圖片綁定時爲了方便給todoItem增加了一個StorageFile字段,但是StorageFile是沒辦法保存到DB中去的,因而又要修改TodoItem(增加字段filePath)了。
思路變成:
選擇圖片—保存到LocalFolder—將相應路徑寫入TodoItem。不完成這個就不能開始服務的添加。

修改TodoItem及株連(?)的代碼

由於只要有StorageFile對象就可以寫入本地,只修改ViewModel內部即可 。
這裏的保存事實上是一種複製。弄清楚這個,使用:

uwp storagefile copy to localfolder

進行搜索,就找到了很多相關答案。

winrt-c-sharp-copy-image-from-asset-to-localstorage

StorageFile file =...;
await file.CopyAsync(ApplicationData.Current.LocalFolder, "image.png");

4. 用StringBuilder編寫查詢結果

sb.AppendFormat("Title: {0}  Description: {1}  Time: {2}", i.title, i.description, i.date.ToString());
                    sb.Append('\n');

5. 啓動app時從數據庫創建listview

實現圖片從數據庫讀入的思路
使用filePath保存—-啓動app時在viewmodel同步listview—使用一個異步函數封裝同步操作,進行循環的大量的文件讀取,加載bitmapimage
實現:
其實根本不用保存filePath,因爲圖片都唯一對應item,而且名字就是item.id。
會出現問題的是圖片類型,此處有兩個選擇
1.加載時對多種類型進行測試
2.寫入todoitem

雖然說寫入todoitem好像也不是一個好選擇,但是測試類型的話太耗時了。還是選擇寫入Todoitem。

Debug

首先遇到的問題是,添加項時,如果不選擇圖片,一添加就會出錯。
即使在viewmodel的添加函數裏默認設置它的bitmapimage居然也不行。
——通過Debug工具查看變量值,犯了低級錯誤:在應該使用類成員的地方用了局部變量
然後(StorageFileObject.fileType中是包含”.”的,不用自己添加。

之後開始測試數據庫部分。
1.增加/刪除
用可視化工具輔助。先尋找一下DB創建到哪兒去了。。
username/appdata/package/…
包名在manifest裏可以找到。

BUG_02:增加雖然調用了dbManager的函數,但是並沒有插入到數據庫中,不知道什麼原因。。明明跟樣例是一模一樣的。

—-原因也是很弱智,INSERT裏面我忘記插入Id字段了……只要schema不同插入都會失敗。。
2.查詢
注意通配符的語法.

 WHERE Description LIKE '%'+@SearchTerm+'%'

而且通配時不用bind參數,要分情況處理。
3.更新
圖片綁定的部分需要處理一下……

BUG_03:查詢結果的dialog不知道爲什麼好像只能顯示一行,經過調試stringbuilder的內容明明是正確的。

—-還是弱智錯誤:應該使用.Content屬性,而不是.Title。

BUG_04:查詢爲空時沒有提示信息。

—–查詢按鈕增加處理即可。

BUG_05:Create之後form不清空。

—–done

BUG_06: 寫入數據庫的圖片格式和實際不匹配。

—–忘記修改DBmanager中的更新函數

BUG_07: 無法複製已存在的文件

—-複製前先檢查是否存在,用探測的方法。

var flag = StorageFile.GetFileFromPathAsync(pathToCopy);
    if (flag == null)
     await f.CopyAsync(ApplicationData.Current.LocalFolder, nameOfImg);

BUG_08:刪除後form不清空。

——done.

BUG_09: appbarbutton上的edit,點擊後子頁的圖片不改變

—–在Menuflyoutitem_Edit_Clicked處添加

佈局

太噁心了,佈局真的太噁心了,各種巨難控制。如果沒有出現想要的效果,一定要先刪除掉所有的width,margin,height,alignment等等參數!
更好的設計方法是從一開始先確定好結構,而不要邊測試邊修改,實在是太耗時了。而且由於XAML語言,嵌套grid會變得非常難讀且噁心。

感想

1.類比和推理的能力非常重要。
2.設計數據模型的時候要考慮清楚可擴展性,同時保存一些低級的原始數據,否則就會出現像這兩次這樣修改Todoitem的同時大面積修改應用的慘劇
3. 一定要弄清楚問題,纔可能找到更好的結果;但有時候問題也是在不斷的搜索中變清晰的,所以從搜索開始,再慢慢思考哪些結果是需要的
4. 不使用含有completed字段的表雖然能滿足作業需求,但顯然是不合理的。

實驗結果

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章