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类并在顶部加上如下引用

1 using NSCPAndroid.SQLite;

2.创建一个映射类

有过一定开发经验的人一定会很熟悉ORM,笔者平时用的最多的就是EFCastle Active Record。当然还有很多其他更优秀的框架。不熟悉的人也没有关系,下面我们只是新建一个类,而这个类的结构完全是对应到数据库中的表的。比如笔者在这里创建一个名为Stock的表:

1 [Table("Stock")]
2 public class StockTable
3 {
4 [PrimaryKey, AutoIncrement, Column("_id")]
5 public int Id { get; set; }
6
7 [MaxLength(8)]
8 public string Symbol { get; set; }
9 }

其中我们可以看到Table这个注解属性,含义就是这个类对应到数据库中的表名。 读者不要误认为是依照类名,下面就是两个字段其中关键的就是主键,因为SQLite规定主键必须由自身维护,所以这里我们使用了PrimaryKey注解 属性表示该属性为主键,AutoIncrement表示该主键为自增,最后就是Column表示该字段对应到该表的字段名(名字必须为_id),下面一个 就是我们自己的字段了,笔者使用了MaxLength表示该字段最大可以保存八个字符。

关于更多的注解属性可以看下面的介绍。

[PrimaryKey]:表示该表的主键,只能用于Int类型的属性。

[AutoIncrement]:用于需要自增的属性,每插入一条新数据该字段都会自增,只能用于Int类型。

[Column(name)]:用来表示指定属性对应到表中字段的名称,如果不加该属性则表中的字段名与属性名相同。

[Table(name)]:用来表示指定类对应到数据库中的表名称,如果不加该属性则数据库中的表名称与该类名称相同。

[MaxLength(value)]:用来限制字段能够保存的最长字符长度。

[Ignore]:表示忽略该属性,从而不会在表中生成对应的字段。

[Unique]:表示该属性的值必须在表中唯一。

3.创建数据库连接

我们需要指定数据库所保存的路径,同时还要打开该数据库。如果不存在该数据库,则会自动创建该文件。下面的代码我们将获取数据库的路径并打开该数据库:

1 string dbPath = Path.Combine(System.Environment.
2 GetFolderPath(System.Environment.SpecialFolder.Personal),"ormdemo.db3");
3 var db = new SQLiteConnection(dbPath);

这里要注意我们用的是SQLiteConnection打开该数据库的,而不是SqlConnection。成功打开该数据库之后剩下的工作我们只需要利用db就可以轻松完成了,到现在为止我们仅仅创建了一个空的数据库,里面还不存在任何表。

4.创建表

第2步我们已经创建好了一个表的结构,下面我们将在数据库中创建对应的表,我们只需要通过下面的代码就可以轻松的创建一个表了:

1 db.CreateTable<StockTable>();

或者下面这个方式也一样可以:

1 db.CreateTable(typeof(StockTable));

创建完之后表还是空的,所以接下来我们需要插入几条数据,这样才能介绍其他的操作。

注:实际运用中一定会有人想找如何判断该表是否已经创建的方法,其实没有必须要找,即使重复的执行该操作,也不会影响什么,表一旦创建之后在执行就不会重新创建了。

5.插入数据

这里我们直接通过创建StockTable的实例来插入到数据库中,比如下面的代码我们将会插入一条数据:

1 var newStock = new StockTable();
2 newStock.Symbol = "First";
3 db.Insert(newStock);

是不是十分简单,仅仅只需要调用Insert即可,该方法还会返回插入数据的主键。但是这只是插入一条数据,如果我们需要插入多条数据呢?当然不可能用foreach,已经提供了另一个方法InsertAll,比如下面的示例将会同时插入多条数据:

 1 List<StockTable> stocks = new List<StockTable>
2 {
3 new StockTable{
4 Symbol = "First"
5 },
6 new StockTable{
7 Symbol = "Second"
8 }
9 };
10 db.InsertAll(stocks);

如果读者需要验证下是不是插入了,我们可以获取该表有多少数据即可,比如下面的代码:

1 int count = db.Table<StockTable>().Count();

这时表里已经有数据了,下面我们就需要进行查询。

6.查询数据

首先介绍最简单的查询方式,就是依靠id来直接获取。当然我们不需要拼接任何SQL,只需要通过下面这段代码就可以获取id为1的数据了:

1 var item = db.Get<StockTable>(1);

但是大多数情况下我们都需要通过条件语句进行查询,那样我们就需要使用SQL语句了,比如下面的查询语句,我们将查询Symbol开头为“F”的数据:

1 var items = db.Query<StockTable>(" select * from Stock where Symbol like ? ", "F%");

相信那些对技术比较追求的人一定知道Linq,它让我们摆脱的拼接SQL语句的尴尬,使得查询变的简单有趣(复杂的查询还是需要采用SQL,甚至是存储过程等),当然在这里我们依然可以使用这一特性,下面我们将上面的代码改写成Linq

1 var items = (from item in db.Table<StockTable>()
2 where item.Symbol.StartsWith("F")
3 select item).GetEnumerator();

笔者为了能够更快的查看结果,所以使用了GetEnumerator,实际使用中不一定需要。如果读者喜欢最原始的查询可以用ExecuteScalar方法。

注:linq的查询是属于延迟查询的,意味着在查询的那一刻并没有把结果查询出来,而是等待你使用它的时候才查询。

推荐:

1.Jesse Liu的随笔《快乐的lambda表达式》,个人感觉很有意思,也很有用。

2.关于Linq如何实现动态查询的文章点我,动态查询可以认为是用字符串拼接Linq的部分语句,这样做的目的是为了解决某些特殊场合下的使用。

关于查询数据到此结束了,下面我们将学习剩下的两个操作分别是更新和删除。

7.更新和删除数据

首先我们先将更新数据,因为它的操作跟插入数据是一样的存在UpdateUpdateAll,只是数据的主键需要有数据,否则无法定位是更新哪个数据,下面我们将演示如何利用Update更新数据:

1 var result = (from item in db.Table<StockTable>()
2 where item.Symbol.StartsWith("F")
3 select item).First();
4 result.Symbol = "Third";
5 db.Update(result);
6
7 result = db.Get<StockTable>(result.Id);

既然是更新当然需要先获取一条数据然后更新,最后还要从数据库中拿出来,确定是否已经更新成功。下面我们继续删除操作:

1 var result = (from item in db.Table<StockTable>()
2 where item.Symbol.StartsWith("T")
3 select item).First();
4
5 db.Delete<StockTable>(result.Id);

如果你需要删除整个表的数据只需要使用DeleteAll即可,当然这些操作都是有限的,所以我们还需要支持SQL的方法,那么我们可以使用Execute即可。

Xamarin.Android开发实践(十三)的更多相关文章

  1. Xamarin.Android开发实践(五)

    原文:Xamarin.Android开发实践(五) 一.服务的生命周期 服务与活动一样,在它的整个生命周期中存在着一些事件,下图可以很好解释整个过程以及涉及到的方法: 在真实的使用中,Service来 ...

  2. Xamarin.Android开发实践(四)

    原文:Xamarin.Android开发实践(四) Xamarin.Android下获取与解析JSON 一.新建项目 1.新建一个Android项目,并命名为为NetJsonList 2.右击引用,选 ...

  3. Xamarin.Android开发实践(三)

    原文:Xamarin.Android开发实践(三) 一.前言 用过Android手机的人一定会发现一种现象,当你把一个应用置于后台后,一段时间之后在打开就会发现应用重新打开了,但是之前的相关的数据却没 ...

  4. Xamarin.Android开发实践(二)

    原文:Xamarin.Android开发实践(二) 一.准备 开始学习本教程前必须先完成该教程http://www.cnblogs.com/yaozhenfa/p/xamarin_android_qu ...

  5. Xamarin.Android开发实践(一)

    原文:Xamarin.Android开发实践(一) 一.准备工作 1.创建一个空的解决方案,并命名为Phoneword 2.右击解决方案 新建->新建项目 并命名为Phoneword_Droid ...

  6. Xamarin.Android开发实践(十七)

    Xamarin.Android之定位 一.前言 打开我们手中的应用,可以发现越来越多的应用使用了定位,从而使我们的生活更加方便,所以本章我们将学习如何在Xamarin中进行定位的开发. 二.准备工作 ...

  7. Xamarin.Android开发实践(十五)

    Xamarin.Android学习之应用程序首选项 一.前言 任何App都会存在设置界面,如果开发者利用普通控件并绑定监听事件保存设置,这 一过程会非常的枯燥,而且耗时.我们可以看到Android系统 ...

  8. Xamarin.Android开发实践(十四)

    Xamarin.Android之ListView和Adapter 一.前言 如今不管任何应用都能够看到列表的存在,而本章我们将学习如何使用Xamarin去实现它,以及如何使用适配器和自定义适配器(本文 ...

  9. Xamarin.Android开发实践(十一)

    Xamarin.Android之使用百度地图起始篇 一.前言 如今跨平台开发层出不穷,而对于.NET而言时下最流行的当然还是 Xamarin,不仅仅能够让我们在熟悉的Vs下利用C#开发,在对原生态类库 ...

随机推荐

  1. javaweb学习总结(三十)——EL函数库

    一.EL函数库介绍 由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,SUN公司针对于一些常见处理定义了一套EL函数库供开发者使用. 这些EL函数在JSTL开发包中进行描述,因此在JSP页 ...

  2. VS2010+OpenCV2.4.6永久性配置方法

    1. 配置OpenCV环境变量 计算机->(右键)属性,出现如图1所示界面 单击“高级系统设置”,选中高级(标签)出现如图2所示界面 单击右下方的“环境变量”,弹出如图3所示界面,注意这里最好用 ...

  3. memcached 缓存服务器

    Memcached 缓存服务器 Memcached 是高性能的分布式内存缓存服务器. 一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态web应用的速度.提高可扩展性. 主要特点 ...

  4. C语言之参数传递

    学了四年的计算机,一直让自己比较苦恼的问题是C语言的参数传递问题,之所以说是苦恼,是因为在某年的一个学期,不幸接触到数据结构,光一个链表就把自己弄得死去活来的,而且自已一直就楞以为在操作的过程中,传递 ...

  5. EL表达式从request和session中取值

    在Action中保存登录的基本信息:request.getSession().setAttribute("adminid", str); 在JSP页面中:${sessionScop ...

  6. linux 的useradd 命令的p选项

     linux 的useradd 命令的p选项                错误用法: #useradd   gaojian   -p  gaojian                      #  ...

  7. First Missing Positive

    不好想,用桶排序解决. int findMissingPostive(int A[], int n) { bucket_sort(A, n); ; i < n; i++) ) ; ; } voi ...

  8. HDOJ 2097

    #include<stdio.h> int func(int n,int k) { ; a=n; ) { b+=a%k; a=a/k; } return b; } int main() { ...

  9. Gson @Expose熟悉和@SerializedName属性

    这两个属性一般配套使用. 1.@Expose标签的2个属性.     deserialize (boolean) 反序列化 默认 true        serialize  (boolean) 序列 ...

  10. 15 day 1代碼

    第一题 用堆维护. #include <cstdio> #include <algorithm> #include <queue> int n,i,f[400000 ...