微软WP7本机数据库解决方案之SQLite

数据库 其他数据库 数据库运维
篇幅所限,我仅介绍在Windows Phone 7系统中使用Sqlite Client for Windows Phone编程的部分技巧。

无论是从用户的角度来看还是从开发人员的角度来看,Windows Phone 7给我们带来众多的新的和令人振奋的功能。与此同时,当前的Windows Phone 7系列也的确存在令许多用户失望的缺憾。一个代表性的遗憾便是,Windows Phone 7缺乏本地数据库API支持—当前的Windows Phone 7操作系统仅提供通过XML、客户端独立存储和云存储等几种有限的数据访问支持。那么,就本地数据库功能来说,我们真的有没有其他的选择了吗?当然不是这样。如今各种开源社团如火如荼,已经有一些开发人员和团队一直努力在填补这一方面的空白。

请注意,尽管目前已有多个尝试实现了Windows Phone 7本地数据库支持,但***,这些系统都需要运行于Windows Phone 7提供的独立存储基础之上。在本系列文章中,我将向你介绍上述成员之一-Sqlite Client for Windows Phone。这是一种新的,功能强大且易于使用的Windows Phone 7本机数据库解决方案,该系统公布于着名的开源网站CodePlex。篇幅所限,我仅介绍在Windows Phone 7系统中使用Sqlite Client for Windows Phone编程的部分技巧。

[备注]本系列文章中的案例程序调试环境包括:

  1. Windows 7;
  2. .NET 4.0;
  3. Visual Studio 2010;
  4. Windows Phone Developer Tools RTW;
  5. Sqlite Client for Windows Phone (http://sqlitewindowsphone.codeplex.com/);
  6. (推荐) sqlite-manager (http://code.google.com/p/sqlite-manager/);
  7. (推荐) MVVM Light Toolkit (http://mvvmlight.codeplex.com/).

一、Sqlite Client for Windows Phone简介

大家都知道,SQLite是一个着名的开源的嵌入式的数据库系统,目前已经提供对于iOS和Android的良好支持。在此,应当让我们感谢Dan Ciprian Ardelean,是他带给我们WP7版本的SQLite-C#-SQLite!最近几个月,作者对早期的版本又进行了更新,得到一个功能更强大和更容易使用的解决方案,改名为Sqlite Client for Windows Phone,在知名的开源网站CodePlex上发布,网址是http://sqlitewindowsphone.codeplex.com/releases。

 

▲图1. 下载Sqlite Client for Windows Phone的界面截图

Sqlite Client for Windows Phone进行大范围的更新,如提供对于布尔类型、大型数据(Blobs)以及事务的全面支持,此外,下载包中还一并提供了一个全面的示例,供开发者学习之用。

 

▲图2. Sqlite Client for Windows Phone源码工程及示例工程架构

接下来的操作就很简单了:重新构建源码工程,得到一个程序集Community.CsharpSqlite.WP.dll(Release版本大小是525 KB)。然后,在你的WP7 Silverlight 项目中添加对该程序集的引用。***,你便可以使用Sqlite Client for Windows Phone提供的本地数据库支持功能了。

#p#

二、Sqlite Client for Windows Phone基础类库剖析

如果您以前有过任何基于SQL脚本的数据库编程经验,那么您可以轻松地使用Sqlite Client for Windows Phone功能。特别值得一提的是,此工程建基于以前的C#-SQLite项目之一,通过引入几个帮助器类(在文件SQLiteClient.cs),即SQLiteException、SQLiteConnection和SQLiteCommand,进一步简化了基本的数据库和表相关操作。接下来的几幅图展示了Sqlite Client for Windows Phone中提供的主要组件及其之间的关联关系。

 

▲图3. Sqlite Client for Windows Phone最顶层组件

 

▲图4. SQLiteConnection类中的主要组件

▲图5. SQLiteCommand类中的主要组件

怎么样!如果您以前熟悉任何基于SQL的数据库开发,相信上面的这些组件对您会非常亲切吧。

先别急,在正式使用Sqlite Client for Windows Phone之前,有必要再向您介绍另外一个非常有用的工具,名为sqlite-manager (http://code.google.com/p/sqlite-manager/)。这个工具是以FireFox插件的方式提供的。到现在您应该明白了,绝大多数与SQLite数据库相关的操作,例如创建SQLite数据库、表、视图、索引等等,都可以通过sqlite-manager轻松完成。

1.使用SQLite Manager简化数据库管理

如前所述,SQLite Manager是一个Firefox插件,使用Firefox的加载项管理器你可以很容易地获取和安装这个控件(图6)。

 

▲图6. 使用Firefox的加载项管理器获取和安装SQLite Manager插件

如图所示,如果你打开Firefox的插件管理器,然后输入“SQLite Manager”搜索文本,你会很容易检索到此加载项。然后,您可以点击按钮“添加到Firefox... ”开始下载并安装SQLite Manager。请注意,在Firefox的提示后,你应该重新启动Firefox以完成安装。

使用SQLite Manager是容易的。说实在的,这是我***次使用SQLite Manager,我发现这个工具功能强大而且极易上手。如果您使用过VB6中,你可能熟悉其中内置的数据库管理工具-VisData(以便以内置方式创建小型的Access数据库)。说实话,VisData确实是不容易使用,但在当时我们觉得已经相当不错了。现在,你只须记住,SQLite Manager的功能要比VisData强大1000倍。下图展示了SQLite Manager的一个使用快照。

 

▲图7. SQLite Manager使用快照

从图中可见,你可以使用SQLite Manager来实现几种各种SQLite相关操作。请注意,要想了解更多的有关于SQLite的概念及详细使用语法,请从这款插件的帮助菜单中寻找答案。

另外,你也会注意到,在本文简单的示例工程中,我仅创建了一个表格Customer,对应的数据库文件为database1.sqlite(如图8所示)。

 

▲图8. 使用SQLite Manager定义表格Customer字段

在创建完数据库database1.sqlite后,关闭SQLite Manager插件。然后,把此文件复制或移动到对应示例工程WP7SQLiteClient的根目录下。请注意,接下来,把它的Build Action属性设置为Resource模式。设置成这种模式的原因与接下来的操作方式相关。如果选择Content模式,则在后台的示例工程中你需要修改对应的部分源码。

2.一个有用的工具类-DBHelper

如上所述,Sqlite Client for Windows Phone使用众所周知的SQL操作针对典型的数据库操作提供了一个高层次的封装。因此,在Silverlight for Windows Phone 7编程中为了处理SQLite数据库操作,我们可以直接使用在文件SQLiteClient.cs中定义的对象(在源库项目),即SQLiteException、SQLiteConnection和SQLiteCommand等。

虽然Sqlite Client for Windows Phone并没有提供与独立存储的直接互动,但显然增加对独立存储支持是必要的,这样可以改善系统的性能。因此,我们可以进一步封装前面提到的SQLiteClient对象。为此,Chris开发了一个非常好用的实用工具类,叫做DBHelper。为了应用于我们自己的示例,我对它做了轻微的修改。完整的源码如下。

#p#

列表1:更新版本的工具类DBHelper

  1. //others omitted…  
  2. using SQLiteClient;  
  3. using System.Linq;  
  4. using System.IO.IsolatedStorage;  
  5. using System.Collections.Generic;  
  6. using System.Collections.ObjectModel;  
  7. namespace WP7SQLiteClient.Helpers  
  8. {  
  9.    public class DBHelper  
  10.    {  
  11.       private String _dbName;  
  12.       private SQLiteConnection db = null;  
  13.       public DBHelper(String assemblyName, String dbName)  
  14.       {  
  15.          IsolatedStorageFile store =IsolatedStorageFile.GetUserStoreForApplication();  
  16.          if (!store.FileExists(dbName))  
  17.          {  
  18.             CopyFromContentToStorage(assemblyName, dbName);  
  19.          }  
  20.          _dbName = dbName;  
  21.       }  
  22.       ~DBHelper()  
  23.       {  
  24.          Close();  
  25.       }  
  26.       private void Open()  
  27.       {  
  28.          if (db == null)  
  29.          {  
  30.             db = new SQLiteConnection(_dbName);  
  31.             db.Open();  
  32.          }  
  33.       }  
  34.       private void Close()  
  35.       {  
  36.          if (db != null)  
  37.          {  
  38.             db.Dispose();  
  39.             db = null;  
  40.          }  
  41.       }  
  42.       //Insert operation  
  43.       public int Insert(T obj, string statement) where T : new()  
  44.       {  
  45.          try 
  46.          {  
  47.             Open();  
  48.             SQLiteCommand cmd = db.CreateCommand(statement);  
  49.             int rec = cmd.ExecuteNonQuery(obj);  
  50.             return rec;  
  51.          }  
  52.          catch (SQLiteException ex)  
  53.          {  
  54.             System.Diagnostics.Debug.WriteLine("Insert failed: " + ex.Message);  
  55.             throw ex;  
  56.          }  
  57.       }  
  58.       // Delete operation  
  59.       public void Delete(string statement) where T : new()  
  60.       {  
  61.          try 
  62.          {  
  63.             Open();  
  64.             SQLiteCommand cmd = db.CreateCommand(statement);  
  65.             cmd.ExecuteNonQuery();  
  66.          }  
  67.          catch (SQLiteException ex)  
  68.          {  
  69.             System.Diagnostics.Debug.WriteLine("Deletion failed: " + ex.Message);  
  70.             throw ex;  
  71.          }  
  72.       }  
  73.       //Query operation  
  74.       public List SelectList(String statement) where T : new()  
  75.       {  
  76.          Open();  
  77.          SQLiteCommand cmd = db.CreateCommand(statement);  
  78.          var lst = cmd.ExecuteQuery();  
  79.          return lst.ToList();  
  80.       }  
  81.       public ObservableCollection SelectObservableCollection(String statement)  
  82.       where T : new()  
  83.       {  
  84.          List lst = SelectList(statement);  
  85.          ObservableCollection oc = new ObservableCollection();  
  86.          foreach (T item in lst)  
  87.          {  
  88.             oc.Add(item);  
  89.          }  
  90.          return oc;  
  91.       }  
  92.       private void CopyFromContentToStorage(String assemblyName,String dbName)  
  93.       {  
  94.          IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();  
  95.          System.IO.Stream src = Application.GetResourceStream(  
  96.                                 new Uri("/" + assemblyName + ";component/" + dbName,UriKind.Relative)).Stream;  
  97.          IsolatedStorageFileStream dest = new IsolatedStorageFileStream(dbName,  
  98.                                           System.IO.FileMode.OpenOrCreate,  
  99.                                           System.IO.FileAccess.Write, store);  
  100.          src.Position = 0;  
  101.          CopyStream(src, dest);  
  102.          dest.Flush();  
  103.          dest.Close();  
  104.          src.Close();  
  105.          dest.Dispose();  
  106.       }  
  107.       private static void CopyStream(System.IO.Stream input,IsolatedStorageFileStream output)  
  108.       {  
  109.          byte[] buffer = new byte[32768];  
  110.          long TempPos = input.Position;  
  111.          int readCount;  
  112.          do 
  113.          {  
  114.             readCount = input.Read(buffer, 0, buffer.Length);  
  115.             if (readCount > 0)  
  116.             {  
  117.                output.Write(buffer, 0, readCount);  
  118.             }  
  119.          } while (readCount > 0);  
  120.          input.Position = TempPos;  
  121.       }  
  122.    }  

顺便说一句,对于上面这个帮助类我也没有提供细致的优化编码。希望读者根据您的相关工作能够继续进行这项工作(例如提供更好的泛型化的CRUD支持)并分享给广大网友。简言之,我主要是增加了插入和删除方法。上面的代码中最引起您注意是地方一定是方法CopyFromContentToStorage,正是借助这个方法我们实现了上述目标-建立起SQLite数据库与独立存储的关系。

三、小结

本文中简要介绍了Sqlite Client for Windows Phone的主要功能及相关的辅助开发工具。在接下来的第二篇文章中,我们将具体构建一个简单的Windows Phone 7客户端应用程序,当然要涉及到Sqlite Client for Windows Phone的基本编程技巧。

【编辑推荐】

  1. 微软WP7本地数据库之Sterling编程技巧
  2. 告诉你如何解决MySQL server has gone away问题
  3. 数据库中分组字符串相加
  4. SQL点滴之收集SQL Server线程等待信息
  5. 数据库的性能已成重多厂商关注的焦点
责任编辑:艾婧 来源: it168
相关推荐

2011-05-18 10:21:53

SQLite

2011-05-12 10:25:14

WP7数据库Sterling

2012-06-21 09:07:22

微软WP7WP8

2011-02-28 10:42:14

Windows Pho微软

2011-05-12 13:03:36

WP7数据库选择

2011-04-27 09:58:56

Windows PhoLBS微软

2011-03-29 13:03:59

IronRubyWindows Pho.NET

2011-07-27 09:53:39

MangoWindows Pho微软

2012-07-06 09:26:13

Windows PhoWindows Pho

2012-03-04 20:55:33

WP7

2011-05-10 08:53:46

iOSWindows Pho开发者

2011-06-10 09:03:36

AndroidWindows Pho开发者

2011-08-19 09:09:01

AndroidWP7Windows Pho

2012-01-01 19:33:19

2013-10-18 15:27:30

微软大数据微软

2013-06-17 13:47:41

WP7开发Windows Pho文本框水印控件

2011-02-01 17:44:22

Windows PhoAndroid微软

2011-03-07 16:42:05

MySQL数据库安全

2009-11-18 16:10:00

2013-06-17 14:10:08

WP7开发Windows Pho豆瓣电台
点赞
收藏

51CTO技术栈公众号