现操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字段的表虽然能满足作业需求,但显然是不合理的。

实验结果

这里写图片描述

这里写图片描述

这里写图片描述

猜你喜欢

转载自blog.csdn.net/mukae1997/article/details/68928693