科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件用不到140行C-sharp代码开发面向对象的数据库(上篇)

用不到140行C-sharp代码开发面向对象的数据库(上篇)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

作者:builder.com.cn 2007年2月27日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

搜索数据存储区

这个项目的目标要求两种类型的搜索,而这必须通过在数据库里使用不同的方法来解决。第一个目标是让查询一级C#语句运行。这意味着查询必须是类型安全型的,能够提供IntelliSense,而且可以被编译成IL代码。其中首当其冲的选择是将Predicate(谓词)方法作为查询机制。这让你能够利用内置的C#功能的优势,避免通过草图编写查询机制。

Predicate方法对真正的对象有效,而对序列化的数据(第3项要求)无效。因此我们必须首先将正在被查询的对象反序列化,然后对它们运行Predicate方法。这是这种查询执行方式的一个主要不足之处,也是为什么特别查询会成为该项目的一个目标的原因。在对象被搜索和反序列化之后,我们就对它们运行一个Predicate方法。下面就是示例查询,它会搜索带有“Zach”的FirstName的第一个Customer对象:

    Customer customer = Customer.GetSingle<Customer>(
        delegate(Customer search)
        {
            return search.FirstName == "Zach";
        });

正如你看到的,在这个查询里没有对OODB的直接参考。这是因为Customer对象是从XmlDBBase对象继承过来的,后者提供了搜索、保存和删除的功能。

项目目标所要求的另外一个查询机制是特别查询(第4项要求)。这些查询不是类型安全型的,所以应该要比类型安全型的查询速度快。实现这一目标的最简单方法是使用XPath。有了XPath,我们可以利用一个XPath表达式来查询XML数据库文件,接受一组被作为结果的对象节点,然后把这些对象节点反序列化为真正的对象。这种做法的优势在于不用将正在被搜索的所有对象都序列化,而且要比使用谓词方法快得多。在测试中,Predicate方法搜索10,000个对象大约需要使用1秒钟。而使用XPath查询搜索相同数量的对象并返回同样的结果只需要百分之一秒。

列表B是一个利用“Zach”的FirstName搜索第一个Customer对象的特别查询。

列表B

    Customer customer =
Customer.GetSingle<Customer>("FirstName = 'Zach'");

如果都是对同一个数据存储区进行搜索的话,这个查询所返回的结果与先前使用Predicate方法返回的结果相同。

删除和更新对象

由于我们所有的数据都保存都在XML里且能够通过XmlDocument类访问到,因此更新和删除数据就相对比较简单了。对于删除数据(第5项要求),我们将使用XPath类寻找一个保存有对象组的节点,这些对象的类型与我们正在删除的对象的类型相同。在找到组的节点之后,我们使用XmlNode.RemoveChild方法,将当前对象的Node(节点)属性作为一个参数传递。要让更改最后完成,我们只需要用XmlDocument.Save方法将XML文档写回到磁盘就行了。

对象删除的示例见列表C

列表C

    Customer customer = Customer.GetSingle<Customer>(
        delegate(Customer search)
        {
            return search.FirstName == "Billy";
        });

    if (customer != null)
        customer.Delete();

第5项要求需要我们提供一种“深度删除”对象的机制。这其中的含义就是在删除一个包含子级的对象时,我们必须提供一种能够删除父对象和子对象而不需要用户手动操作的方式。要实现这一目标,我们就要使用反射并在父对象的属性里循环,找到被序列化的子对象并删除它们。

更新对象(第6项要求)是一个简单的工作,你首先删除保存在数据库里的当前对象,然后插入更新过的对象就可以了。删除的方法和上面提到的方式相同。被更新的对象然后就以保存新对象的方式被保存。但是这种方式会给我们的数据库带来一个很严重的问题,如果你是想要构建一个企业级的OODB的话,有个问题的就必须被解决。这个问题就是,没有对正在被删除的对象进行任何检查以保证其没有被系统里的其他对象所需要。

更新的示例见列表D

列表D

    Customer customer =
        Customer.GetSingle<Customer>(
        delegate(Customer search)
        {
            return search.FirstName == "Brad";
        });

    customer.LastName = "Cunningham";
    customer.Save();

保存在数据库里的对象的要求

这个项目对我们的一个要求是,对象不能告诉数据库它们是被如何保存的。当然,对象必须满足一些条件才能够被保存在数据库里。这些条件通过一个叫做“IXmlDBSerializable”的接口来强制实现。这个接口要求任何被保存在数据库的对象都必须具有下列属性:

    System.Guid Identity { get; set; }
    System.Xml.XmlNode Node { get; set; }

以及下列方法:

    void Save(bool persistData);

我们需要Identity(标识)属性,因为我们能够用它识别出数据库里每个不同的对象。Node属性专门用来保存XML Node对象,而对象就被保存在数据库的Node对象里。Save(保存)方法也是需要的,这样对象就可以被保存在数据库里。

本系列的下篇

在本系列文章的下篇里,我将告诉你这些概念背后的代码,并解释它是如何在示例项目里实现的。单个的概念很容易理解,但是将它们组合在一起成为一段有效的代码及可能会造成一些困惑。我要在下一篇文章里谈到的代码放在示例对象里,可以在这里找到。

责任编辑:德东

查看本文的国际来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章