Xamarin.Android之SQLite.NET ORM
一、前言
通过《Xamarin.Android之SQLiteOpenHelper》和《Xamarin.Android之ContentProvider》的学习,我们已经掌握了如何使用特定于该平台的数据库操作。但是这样却和Xamarin所宣称的跨平台相违背了,因为这样我们就需要针对不同的平台编写不同的代码,而本章将使用Github上的开源项目SQLite.NET去解决这个问题,从而可以实现跨平台,减少代码的重复。
二、准备工作
因为这个库很大,而我们只需要其中的一个.cs文件就可以了,所以笔者这里已经封装好了一个库,里面不仅包含了这个库,还包含了可以跨平台的网络连接。
因为该库还使用了一个json库,所以读者也一并要下载并引用
然后新建一个Android Application项目(.net 4.0)并且SDK版本设置为14(Android 4.0),下面我们就可以开始正式学习了。
三、正文
1.引用命名空间
打开MainActivity类并在顶部加上如下引用
- using NSCPAndroid.SQLite;
2.创建一个映射类
有过一定开发经验的人一定会很熟悉ORM,笔者平时用的最多的就是EF、Castle Active Record。当然还有很多其他更优秀的框架。不熟悉的人也没有关系,下面我们只是新建一个类,而这个类的结构完全是对应到数据库中的表的。比如笔者在这里创建一个名为Stock的表:
- [Table("Stock")]
- public class StockTable
- {
- [PrimaryKey, AutoIncrement, Column("_id")]
- public int Id { get; set; }
- [MaxLength()]
- public string Symbol { get; set; }
- }
其中我们可以看到Table这个注解属性,含义就是这个类对应到数据库中的表名。读者不要误认为是依照类名,下面就是两个字段其中关键的就是主键,因为SQLite规定主键必须由自身维护,所以这里我们使用了PrimaryKey注解属性表示该属性为主键,AutoIncrement表示该主键为自增,最后就是Column表示该字段对应到该表的字段名(名字必须为_id),下面一个就是我们自己的字段了,笔者使用了MaxLength表示该字段最大可以保存八个字符。
关于更多的注解属性可以看下面的介绍。
[PrimaryKey]:表示该表的主键,只能用于Int类型的属性。
[AutoIncrement]:用于需要自增的属性,每插入一条新数据该字段都会自增,只能用于Int类型。
[Column(name)]:用来表示指定属性对应到表中字段的名称,如果不加该属性则表中的字段名与属性名相同。
[Table(name)]:用来表示指定类对应到数据库中的表名称,如果不加该属性则数据库中的表名称与该类名称相同。
[MaxLength(value)]:用来限制字段能够保存的最长字符长度。
[Ignore]:表示忽略该属性,从而不会在表中生成对应的字段。
[Unique]:表示该属性的值必须在表中唯一。
3.创建数据库连接
我们需要指定数据库所保存的路径,同时还要打开该数据库。如果不存在该数据库,则会自动创建该文件。下面的代码我们将获取数据库的路径并打开该数据库:
- string dbPath = Path.Combine(System.Environment.
- GetFolderPath(System.Environment.SpecialFolder.Personal),"ormdemo.db3");
- var db = new SQLiteConnection(dbPath);
这里要注意我们用的是SQLiteConnection打开该数据库的,而不是SqlConnection。成功打开该数据库之后剩下的工作我们只需要利用db就可以轻松完成了,到现在为止我们仅仅创建了一个空的数据库,里面还不存在任何表。
4.创建表
第2步我们已经创建好了一个表的结构,下面我们将在数据库中创建对应的表,我们只需要通过下面的代码就可以轻松的创建一个表了:
- db.CreateTable<StockTable>();
或者下面这个方式也一样可以:
- db.CreateTable(typeof(StockTable));
创建完之后表还是空的,所以接下来我们需要插入几条数据,这样才能介绍其他的操作。
注:实际运用中一定会有人想找如何判断该表是否已经创建的方法,其实没有必须要找,即使重复的执行该操作,也不会影响什么,表一旦创建之后在执行就不会重新创建了。
5.插入数据
这里我们直接通过创建StockTable的实例来插入到数据库中,比如下面的代码我们将会插入一条数据:
- var newStock = new StockTable();
- newStock.Symbol = "First";
- db.Insert(newStock);
是不是十分简单,仅仅只需要调用Insert即可,该方法还会返回插入数据的主键。但是这只是插入一条数据,如果我们需要插入多条数据呢?当然不可能用foreach,已经提供了另一个方法InsertAll,比如下面的示例将会同时插入多条数据:
- List<StockTable> stocks = new List<StockTable>
- {
- new StockTable{
- Symbol = "First"
- },
- new StockTable{
- Symbol = "Second"
- }
- };
- db.InsertAll(stocks);
如果读者需要验证下是不是插入了,我们可以获取该表有多少数据即可,比如下面的代码:
- int count = db.Table<StockTable>().Count();
这时表里已经有数据了,下面我们就需要进行查询。
6.查询数据
首先介绍最简单的查询方式,就是依靠id来直接获取。当然我们不需要拼接任何SQL,只需要通过下面这段代码就可以获取id为1的数据了:
- var item = db.Get<StockTable>();
但是大多数情况下我们都需要通过条件语句进行查询,那样我们就需要使用SQL语句了,比如下面的查询语句,我们将查询Symbol开头为“F”的数据:
- var items = db.Query<StockTable>(" select * from Stock where Symbol like ? ", "F%");
相信那些对技术比较追求的人一定知道Linq,它让我们摆脱的拼接SQL语句的尴尬,使得查询变的简单有趣(复杂的查询还是需要采用SQL,甚至是存储过程等),当然在这里我们依然可以使用这一特性,下面我们将上面的代码改写成Linq:
- var items = (from item in db.Table<StockTable>()
- where item.Symbol.StartsWith("F")
- select item).GetEnumerator();
笔者为了能够更快的查看结果,所以使用了GetEnumerator,实际使用中不一定需要。如果读者喜欢最原始的查询可以用ExecuteScalar方法。
注:linq的查询是属于延迟查询的,意味着在查询的那一刻并没有把结果查询出来,而是等待你使用它的时候才查询。
推荐:
1.Jesse Liu的随笔《快乐的lambda表达式》,个人感觉很有意思,也很有用。
2.关于Linq如何实现动态查询的文章点我,动态查询可以认为是用字符串拼接Linq的部分语句,这样做的目的是为了解决某些特殊场合下的使用。
关于查询数据到此结束了,下面我们将学习剩下的两个操作分别是更新和删除。
7.更新和删除数据
首先我们先将更新数据,因为它的操作跟插入数据是一样的存在Update和UpdateAll,只是数据的主键需要有数据,否则无法定位是更新哪个数据,下面我们将演示如何利用Update更新数据:
- var result = (from item in db.Table<StockTable>()
- where item.Symbol.StartsWith("F")
- select item).First();
- result.Symbol = "Third";
- db.Update(result);
- result = db.Get<StockTable>(result.Id);
既然是更新当然需要先获取一条数据然后更新,最后还要从数据库中拿出来,确定是否已经更新成功。下面我们继续删除操作:
- var result = (from item in db.Table<StockTable>()
- where item.Symbol.StartsWith("T")
- select item).First();
- db.Delete<StockTable>(result.Id);
如果你需要删除整个表的数据只需要使用DeleteAll即可,当然这些操作都是有限的,所以我们还需要支持SQL的方法,那么我们可以使用Execute即可。
Xamarin.Android之SQLite.NET ORM的更多相关文章
- Xamarin android使用Sqlite做本地存储数据库
android使用Sqlite做本地存储非常常见(打个比方就像是浏览器要做本地存储使用LocalStorage,貌似不是很恰当,大概就是这个意思). SQLite 是一个软件库,实现了自给自足的.无服 ...
- Xamarin.Android 使用 SQLite 出现 Index -1 requested, with a size of 10 异常
异常: Android.Database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 10 此错误是数据返回 ...
- Xamarin.Android 使用 SQLite 出现 Couldn't read row 0, col -1 from CursorWindow. 异常
异常:Java.Lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cu ...
- Xamarin.Android开发实践(十四)
Xamarin.Android之ListView和Adapter 一.前言 如今不管任何应用都能够看到列表的存在,而本章我们将学习如何使用Xamarin去实现它,以及如何使用适配器和自定义适配器(本文 ...
- Xamarin.Android开发实践(十三)
Xamarin.Android之SQLite.NET ORM 一.前言 通过<Xamarin.Android之SQLiteOpenHelper>和<Xamarin.Android之C ...
- Xamarin.Android之ListView和Adapter
一.前言 如今不管任何应用都能够看到列表的存在,而本章我们将学习如何使用Xamarin去实现它,以及如何使用适配器和自定义适配器(本文中的适配器的主要内容就是将原始的数据转换成了能够供列表控件显示的项 ...
- Xamarin android 的WebClient Json下载并存储本地及sqlite数据库
这一点雕虫小技可能对熟悉的人来说已经不值一提.但是我想,既然这些都是常用的功能,集成在一起做个笔记也有点意义吧. 首先,json 是传递数据的事实标准了.所以先说一下将它从服务器端下载下来..net ...
- C# Android 开发中使用 Sqlite.NET ORM
开发环境:VS2015 Xamarin Sqlite.NET ORM 不就相当于 Entiry Framework For Xamarin 吗? 相当于用 C# 开发安卓程序访问 Sqlite 可以使 ...
- Android SQLite的ORM接口实现(一)---findAll和find的实现
最近在看Android的ORM数据库框架LitePal,就想到可以利用原生的SQLite来实现和LitePal类似的ORM接口实现. LitePal有一个接口是这样的: List<Status& ...
随机推荐
- Docker存出载入镜像
镜像的存出和载入 如果你的生产环境不能连通互联网,而你又希望从互联网上获取镜像.你就需要借助 docker save命令,可以将镜像导出为 tar 文件.使用 docker load 命令,可以将ta ...
- Google SRE 读书笔记 扒一扒SRE用的那些工具
写在前面 最近花了一点时间阅读了<SRE Goolge运维解密>这本书,对于书的内容大家可以看看豆瓣上的介绍.总体而言,这本书是首次比较系统的披露Google内部SRE运作的一些指导思想. ...
- 程序中try、throw、catch三者之间的关系
c++程序中,采用一种专门的结构化处理逻辑的异常处理机制. 1.try语句 try语句块的作用是启动异常处理机制,检测try语句块中程序语句执行时可能出现的异常. try语句块总是与catch一同出现 ...
- Bluemix结合DevOps Service实现一键部署
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文讲述了怎样通过Bluemix与DevOps Service相结合.来构建与部署一个持 ...
- B. Random Teams(Codeforces Round 273)
B. Random Teams time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- java含有静态代码块新建的时候报错java.lang.ExceptionInInitializerError
问题描述 最近在写一些单元测试用例,为了避免连接外界服务,所有选择mock了数据库Dao层,计划将数据库所需要的数据存在List中,在类加载的时候初始化List并且填充数据.代码如下: public ...
- Pytorch之CrossEntropyLoss() 与 NLLLoss() 的区别
(三)PyTorch学习笔记——softmax和log_softmax的区别.CrossEntropyLoss() 与 NLLLoss() 的区别.log似然代价函数 pytorch loss fun ...
- siamese网络&&tripletnet
siamese网络 - 之前记录过: https://www.cnblogs.com/ranjiewen/articles/7736089.html - 原始的siamese network: 输入一 ...
- RxJava RxLifecycle 生命周期 内存泄漏 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- ARDC Android 远程桌面助手 录屏 演示 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...