轻量级面向对象数据库NDatabase五分钟精通教程
目前为止,NDatabase是最让我心动的面向对象数据库(挤掉了db4o在我心中的位置)。其具体特征什么的我就不详细说了,大家可以参照NDatabase – C# Lightweight Object Database – Home。为了节省时间,下面直接开始教程:
先给出一段代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
using NDatabase; using System; namespace NDBTest { public interface IHero { string Name { get; } double Attack { get; } double Defense { get; } } public sealed class Mage : IHero { public Mage(string name, double attack, double defense) { Name = name; Attack = attack; Defense = defense; } #region Implementation of IHero public string Name { get; set; } public double Attack { get; private set; } public double Defense { get; private set; } #endregion public override string ToString() { return string.Format("[Mage] Name: {0}, Attack: {1}, Defense: {2}", Name, Attack, Defense); } } public sealed class Warrior : IHero { public Warrior(string name, double attack, double defense) { Name = name; Attack = attack; Defense = defense; } #region Implementation of IHero public string Name { get; private set; } public double Attack { get; private set; } public double Defense { get; private set; } #endregion public override string ToString() { return string.Format("[Warrior] Name: {0}, Attack: {1}, Defense: {2}", Name, Attack, Defense); } } class Program { static void Main(string[] args) { const string dbFileName = "game.db"; if (System.IO.File.Exists(dbFileName)) System.IO.File.Delete(dbFileName); const double mageAttackValue = 3.3; const double mageDefenseValue = 3.4; const double warriorAttackValue = 4.4; const double warriorDefenseValue = 2.2; // create two objects IHero mage = new Mage("Merlin", mageAttackValue, mageDefenseValue); IHero warrior = new Warrior("Conan", warriorAttackValue, warriorDefenseValue); // store them using (var odb = OdbFactory.Open(dbFileName)) { odb.Store(mage); odb.Store(warrior); } // retrieve them by classes and by interface using (var odb = OdbFactory.Open(dbFileName)) { var heroes = odb.Query<IHero>().Execute<IHero>(); foreach (var hero in heroes) Console.WriteLine(hero); Console.ReadLine(); } } } } |
大家可能会发现,这段代码虽然有将近100行,但与NDatabase相关的也不足10行,但在这10行里面就实现了多种功能:数据库的打开、数据的存储、数据的查询。只能说完美!
在这不到10行的代码里,有两个下面的using语句,在NDatabase中,强烈推荐所有的数据库操作都在类似的using语句中完成。具体可以参照Best patterns and practices。是NDatabase对别人提问的一个回答,也很好的证明了这个观点。
1 2 3 4 5 |
//第二次打开同一个数据库的时候可以使用OdbFactory.OpenLast() using (var odb = OdbFactory.Open(dbFileName)) { //do something } |
上面的这一句using语句其实就实现了数据库的创建(如果存在就打开)、事件操作。下面是具体的增删改查的操作,非常简单。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
using (var odb = OdbFactory.Open(dbFileName)) { //增 var oid = odb.Store(mage); odb.Store(warrior); //查(这里需要using System.Linq;使用的是LINQ的查询方式) //更多使用方法可以参照微软官方的LINQ使用方法 Mage gotMage = (from temMage in odb.AsQueryable<Mage>() select temMage).First(); //改(一般过程:查找到对象->修改->存储对象) gotMage.Name = "Name Changed"; odb.Store(gotMage); //删 odb.Delete(warrior); odb.DeleteObjectWithId(oid); } |
上面的增和删的操作在实际使用中已经足够了,下文会对改和查操作作进一步的说明。
先说既复杂也简单的查吧。如果你用过LINQ,那么你可以没有任何学习成本的进行非常复杂的查询操作,所以说查询非常简单。
NDatabase共有3种查询方式:SODA(Simple Object Database Access)、Value Query、LINQ。个人喜欢的是LINQ这种通用又简单的查询方法,如果大家学会了这一种方式,在使用C#时,几乎所有主流的数据都可以用这个查询。所以如果你对LINQ还不了解的话就赶快去学习一下吧。SODA也是面向对象数据库中较为通用的一种查询方式,这里不作详细介绍,如果有兴趣可能参照:
NDatabase 5 Minutes Tutorial
最后说一下改:和关系型数据库一样,改必须是在查找出对象的基础上进行的。像我之前在相关于db4o的文章DB4O在进行更新时只能在同一个session中的问题及改进方法中写的一样,查与改与最终的存储要在同一个using语句中。我在DB4O在进行更新时只能在同一个session中的问题及改进方法中给出了一种解决方案,但实际上这种解决方案是非常不完善的,用删除+增加替代更新可能会造成数据库中关系的错乱,比方说使一个对象引用了已经删除了的对象,造成非常大的麻烦。
在NDatabase中,此问题有了比较大的改进,主要是通过两种措施:
1、作者在Best way to use NDatabase in a desktop application?中提到,推荐在数据库使用完毕后立即关闭数据库,在有需要时重新打开。我们可以在每一次更新前打开数据库,将要更新的对象从数据库中查询出来,然后更新,保存,立即关闭数据库。这样可能会存在多次打开关闭数据库的操作。从作者的回复来看,此操作并不会对性能产生较大影响。
2、针对步骤1提出的方案,还有一个问题需要解决,那就是如何快速准确的查询出所需要的对象。这时可以使用OID属性。OID相当于某个类的存放地址,用OID进行查询时速度较快。使用方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//类中将某个变量标记为[OID] public class TestOidClassOID { [OID] private readonly Api.OID _oid; public TestOidClassOID(string value) { Value = value; _oid = null; } public string Value { get; set; } public Api.OID OID { get { return _oid; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//使用方法 OdbFactory.Delete(DbName); const string value = "value"; using (var odb = OdbFactory.Open(DbName)) { odb.Store(new TestOidClassOID(value)); } using (var odb = OdbFactory.Open(DbName)) { var first = odb.QueryAndExecute<TestOidClassOID>().GetFirst(); //此时first.OID就保存着此类的OID } |
这样就可以每次使用OID来进行查询,然后更新。给出一段示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Mage gotMage; using (var odb = OdbFactory.Open(dbFileName)) { odb.Store(mage); //查(这里需要using System.Linq;使用的是LINQ的查询方式) //更多使用方法可以参照微软官方的LINQ使用方法 gotMage = (from temMage in odb.AsQueryable<Mage>() select temMage).First(); } //do something using (var odb = OdbFactory.OpenLast()) { gotMage = odb.GetObjectFromId(gotMage.OID) as Mage; gotMage.Name = "Name Changed!"; odb.Store(gotMage); } |
这样这个问题就完全解决了,心满意足的休息去了。
最近一段写了不少关于面向对象数据库的文章,之后可能很长一段时间内是不会再写了,因为觉得NDatabase在研究中足够完美了,不再折腾了,重新回归到总结自己的工作去了。
原创文章,文章首发于:Riley Ge (@rileyge) — Steemit
原创文章,转载请注明: 转载自TsonTec:测量解决方案提供者
本文链接地址: 轻量级面向对象数据库NDatabase五分钟精通教程
说点什么