原文:Xamarin.Android开发实践(十三)html
经过《Xamarin.Android之SQLiteOpenHelper》和《Xamarin.Android之ContentProvider》的 学习,咱们已经掌握了如何使用特定于该平台的数据库操做。可是这样却和Xamarin所宣称的跨平台相违背了,由于这样咱们就须要针对不一样的平台编写不一样 的代码,而本章将使用Github上的开源项目SQLite.NET去解决这个问题,从而能够实现跨平台,减小代码的重复。android
关于该开源项目请点我git
由于这个库很大,而咱们只须要其中的一个.cs文件就能够了,因此笔者这里已经封装好了一个库,里面不只包含了这个库,还包含了能够跨平台的网络链接。github
点我下载sql
由于该库还使用了一个json库,因此读者也一并要下载并引用数据库
点我下载json
而后新建一个Android Application项目(.net 4.0)而且SDK版本设置为14(Android 4.0),下面咱们就能够开始正式学习了。网络
打开MainActivity类并在顶部加上以下引用app
1 using NSCPAndroid.SQLite;
有过必定开发经验的人必定会很熟悉ORM,笔者平时用的最多的就是EF、Castle 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]:表示该属性的值必须在表中惟一。
咱们须要指定数据库所保存的路径,同时还要打开该数据库。若是不存在该数据库,则会自动建立该文件。下面的代码咱们将获取数据库的路径并打开该数据库:
1 string dbPath = Path.Combine(System.Environment. 2 GetFolderPath(System.Environment.SpecialFolder.Personal),"ormdemo.db3"); 3 var db = new SQLiteConnection(dbPath);
这里要注意咱们用的是SQLiteConnection打开该数据库的,而不是SqlConnection。成功打开该数据库以后剩下的工做咱们只须要利用db就能够轻松完成了,到如今为止咱们仅仅建立了一个空的数据库,里面还不存在任何表。
第2步咱们已经建立好了一个表的结构,下面咱们将在数据库中建立对应的表,咱们只须要经过下面的代码就能够轻松的建立一个表了:
1 db.CreateTable<StockTable>();
或者下面这个方式也同样能够:
1 db.CreateTable(typeof(StockTable));
建立完以后表仍是空的,因此接下来咱们须要插入几条数据,这样才能介绍其余的操做。
注:实际运用中必定会有人想找如何判断该表是否已经建立的方法,其实没有必需要找,即便重复的执行该操做,也不会影响什么,表一旦建立以后在执行就不会从新建立了。
这里咱们直接经过建立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();
这时表里已经有数据了,下面咱们就须要进行查询。
首先介绍最简单的查询方式,就是依靠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的部分语句,这样作的目的是为了解决某些特殊场合下的使用。
关于查询数据到此结束了,下面咱们将学习剩下的两个操做分别是更新和删除。
首先咱们先将更新数据,由于它的操做跟插入数据是同样的存在Update和UpdateAll,只是数据的主键须要有数据,不然没法定位是更新哪一个数据,下面咱们将演示如何利用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便可。