SQL Server CE 和db4o以及XMLdatabase的应用比较
引子
上一篇 (SQL Server、Oracle、db2所提供的简装版(Express)比较) 我针对在应用程序开发中,可能会用到的三款数据库产品的简装版做了一些介绍和比较。如果我们的应用的数据量不是很大,例如不超过4GB,而且用户的并发情况也不多的话,它们是不错的选择。但有一个问题就是,他们都需要在运行环境中,安装相应的数据库引擎,而且相对来说,所占用的内存还不小。如果我们这个应用是一个针对个人用户或者要在终端用户的桌面上运行的的,那么就可能遇到一个部署的障碍。大家试想一下,有多少人愿意在自己的日常工作的电脑上面安装这样的数据库引擎呢?尤其是他们对这些东西又不熟悉的情况下。你可能会苦口婆心地去跟用户解释,动之以情,晓之以理……不过,请打住,用户会跟你说:“Don’t make me think”,
那么,是否有办法实现,不安装任何数据库引擎的情况下,也能完成类似数据库的存取呢?答案是肯定的。这一篇文章,我同样介绍三个产品给大家参考参考。
名词定义和介绍
- SQL Server CE:全称叫SQL Server Compact Edition。这是从SQL Server 2005开始提供的一个特殊版本。原本叫SQL Server Mobile Edition,顾名思义,是定位用在手机开发中的。不过,期间又改过几次名字,我们就不要深究了。目前而言,这个版本可以用于一些脱机的、本地的存取,它继承了SQL Server的优良传统,提供了与SQL Server一致性的访问体验,并且这个数据库可以很容易地与服务器端的SQL Server实现同步。你可以通过微软官方网站了解更多或者进行下载:http://www.microsoft.com/downloads/zh-cn/details.aspx?familyid=85E0C3CE-3FA1-453A-8CE9-AF6CA20946C3&displaylang=zh-cn
- db4o:全称是Open Source Object–Oriented Database ,顾名思义,它是一个开源的、面向对象的数据库。它基于JAVA和.NET分别做了很好的实现,并且对LINQ做了很好的支持。总体来说,这是一款相当不错的产品。它的官方网站在:http://db4o.com/
- XMLdatabase:全称就是xml database,这是我自己做的一个轻型的数据库,目前只提供基于.NET版本的实现。与db4o相同的是,这是也是完全面向对象的,并且支持LINQ语法。然后,不同的是,这个数据库将完全采用XML格式存储所有的数据,而不是二进制。这在当前XML统治一切的时代,是有相当的积极意义的。你可以通过 http://xmldatabase.codeplex.com/ 了解更多,也可以通过 http://nuget.org/List/Packages/XMLDatabase 下载使用
SQL Server CE
如果你本来就比较熟悉SQL Server,并且希望你的这个程序,可以与服务器端实现数据同步,那么你应该优先选用SQL Server CE。
需要注意的是,Local Database Cache是一个特殊的模板,它可以结合Sync Framework实现与服务器端数据库的同步
我们先来看一下简单的Local Database的做法,通过模板创建一个sdf文件之后,双击它,就会自动打开Server Explorer
在这里,你可以像在服务器一样,添加表(注意,只能添加表,没有其他对象,例如视图,存储过程等)
访问SQL Server CE的数据库,实在太简单了。我们可以用ADO.NET Entity Framework来快速建模和访问。注意,它不支持LINQ to SQL.
在应用程序中,你可以通过如下的方式对数据进行查询
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace WindowsFormsApplicationSample { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); //使用LINQ to Entities访问SQL Server CE数据库 //1.创建数据库上下文 var ctx = new UsersEntities(); //2.构造查询 var query = from u in ctx.Employees where u.Email.Contains("xizhang") select u; //3.得到结果 var result = query.ToArray(); //4.执行其他操作(绑定,或者遍历) } } }
通过如下的方式对数据库进行修改,例如新增,删除,更新等
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace WindowsFormsApplicationSample { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); //使用LINQ to Entities访问SQL Server CE数据库 //1.创建数据库上下文 var ctx = new UsersEntities(); //2.新增一条记录 ctx.AddToEmployees(new Employee() { EmployeeId = 1, FirstName = "ares", LastName = "chen", Email = "ares@xizhang.com" }); //3.更新一条记录 var ares = ctx.Employees.FirstOrDefault(e => e.FirstName == "ares"); if(ares != null) ares.Email = "ares@microsoft.com"; //4.删除一条记录 if(ares != null) ctx.DeleteObject(ares); //5.以上三个操作,最终都要通过保存才最终能反应到数据库中 ctx.SaveChanges(); } } }
大家可以看到,这样的语法应该是很好理解。SQL Server CE在这三个产品中,最大的优势就是:它仍然是一个关系型数据库,所有你拥有的关系数据库的知识和经验都可以复用,而且它完全支持XML数据类型。在访问上,它与正常的数据库访问没有什么区别。
更加强大的是,保存在SQL Server CE数据库中可以很方便地与服务器端的SQL Server进行同步。这个功能,需要结合Microsoft Sync Framework. 这对于需要提供脱机支持并且后续需要同步的场景,是多么重要。
限于篇幅,我这里就不一个一个去截图了,有兴趣的朋友,可以参考 http://msdn.microsoft.com/zh-cn/library/bb726002.aspx 进行一些动手实验。
db4o
这是我见过最好的一个嵌入式、面向对象的数据库之一。目前针对.NET 4.0和3.5都分别有安装程序,并且甚至还提供了对Silverlight的支持。
总体而言,它的核心理念是面向对象,就是说,我们可以忘记数据库,忘记SQL语句。我们所有的操作都是利用对象的方式来实现。下面的代码摘自官方提供的Tutorial。可以很清晰地看到它的用法:增、删、改、查
using System; using System.IO; using Db4objects.Db4o; using Db4objects.Db4o.Query; using Db4odoc.Tutorial; namespace Db4odoc.Tutorial.F1.Chapter1 { public class FirstStepsExample : Util { readonly static string YapFileName = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "formula1.yap"); public static void Main(string[] args) { File.Delete(YapFileName); AccessDb4o(); File.Delete(YapFileName); using(IObjectContainer db = Db4oEmbedded.OpenFile(YapFileName)) { StoreFirstPilot(db); StoreSecondPilot(db); RetrieveAllPilots(db); RetrievePilotByName(db); RetrievePilotByExactPoints(db); UpdatePilot(db); DeleteFirstPilotByName(db); DeleteSecondPilotByName(db); } } public static void AccessDb4o() { using(IObjectContainer db = Db4oEmbedded.OpenFile(YapFileName)) { // do something with db4o } } public static void StoreFirstPilot(IObjectContainer db) { Pilot pilot1 = new Pilot("Michael Schumacher", 100); db.Store(pilot1); Console.WriteLine("Stored {0}", pilot1); } public static void StoreSecondPilot(IObjectContainer db) { Pilot pilot2 = new Pilot("Rubens Barrichello", 99); db.Store(pilot2); Console.WriteLine("Stored {0}", pilot2); } public static void RetrieveAllPilotQBE(IObjectContainer db) { Pilot proto = new Pilot(null, 0); IObjectSet result = db.QueryByExample(proto); ListResult(result); } public static void RetrieveAllPilots(IObjectContainer db) { IObjectSet result = db.QueryByExample(typeof(Pilot)); ListResult(result); } public static void RetrievePilotByName(IObjectContainer db) { Pilot proto = new Pilot("Michael Schumacher", 0); IObjectSet result = db.QueryByExample(proto); ListResult(result); } public static void RetrievePilotByExactPoints(IObjectContainer db) { Pilot proto = new Pilot(null, 100); IObjectSet result = db.QueryByExample(proto); ListResult(result); } public static void UpdatePilot(IObjectContainer db) { IObjectSet result = db.QueryByExample(new Pilot("Michael Schumacher", 0)); Pilot found = (Pilot)result.Next(); found.AddPoints(11); db.Store(found); Console.WriteLine("Added 11 points for {0}", found); RetrieveAllPilots(db); } public static void DeleteFirstPilotByName(IObjectContainer db) { IObjectSet result = db.QueryByExample(new Pilot("Michael Schumacher", 0)); Pilot found = (Pilot)result.Next(); db.Delete(found); Console.WriteLine("Deleted {0}", found); RetrieveAllPilots(db); } public static void DeleteSecondPilotByName(IObjectContainer db) { IObjectSet result = db.QueryByExample(new Pilot("Rubens Barrichello", 0)); Pilot found = (Pilot)result.Next(); db.Delete(found); Console.WriteLine("Deleted {0}", found); RetrieveAllPilots(db); } } }
要使用它,其实很简单,只需要添加一个引用即可
同时,它也提供了一个可视化的工具,可以查看数据库里面所有对象。
XMLDatabase
这是我在2009年设计的一个完全基于XML,面向对象的数据库。这个数据库的最终可执行的组件以及源代码,请通过下面地址访问
http://xmldatabase.codeplex.com/
我之前有几篇文章详细介绍了设计的考虑和使用用法
今年,我整理了一下,重新发布到了Nuget Gallary,所以,你要使用的话,会更加简单,如果你使用的是Visual Studio 2010的话
关于如何使用,请参考下面这篇文章的详细介绍,这里就不重复了
XMLDatabase项目已经发布到nuget gallery
总结
本文介绍了三款可用于本地、脱机存储应用程序开发的数据库解决方案。SQL Server Compact Edition与SQL Server一脉相承,使用关系型数据库的机制,提供了一致的数据访问体验。db4o和XMLDatabase都是开源的面向对象数据库,都支持LINQ语法,db4o是用二进制保存数据,而XMLDatabase是以XML格式存储所有数据的。