在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
前言: 说起来,用InstantObjects(以下简称IO)编程还是走了不少弯路的,因为网上资料太少,好在有IO自带了几个demo,尤其是那个Primer.dpr例程,里面有若干IQL的示例,再加上chm文档的参考,大体上还是有一个基本的概念的。 0.缘起 今天写一个博客搬家程序,写着写着,就觉得哪里不对了,因为涉及到文章及图片,需要用到数据库将这些内容的相关信息保存起来,以便增量下载。程序要用到 用户/文章/图片 三级对象的模型,两两是一对多的关系。正要用熟悉的ADO方式来做,还是觉得太笨了。要是有ORM的方式就好了。想起来曾经看到过有类似的工具介绍,上网一查,果然找到了,就是InstantOjbects。 下载,安装。一边看着文档,一边在IDE中新建一个工程,再新建一个unit,起名TestModel.pas,在菜单中选择view,进入设计器。很快的就设计好了三级对象各自属性及互相关系。 轮到生成数据库的时候有问题了,怎么new的时候没有反应呢,为什么文档中的截图里有那么多种数据库可以支持呢?重新看安装文档,原来自己漏掉了好几步。 补上所有的安装步骤,再次建立数据库,成功了。 下一步就是用IO进行编程了。今天太晚了,明天继续。 1.建模 之所以打算用博客搬家的程序做为第一个IO编程的试验,是因为它的业务逻辑及数据结构都超简单,而且涉及了一对多的典型的master-detail模型,正好拿来练手。 言归正传,开始介绍我心目中的数据库结构: ------------------------------ Blogger表: BlogID: string Articles: (该用户发表的所有文章的集合) Article表: Title: string URL: string Filename: string Datetime1: (发表时间) Pictures: (该文章下所有图片的集合) Picture表: URL: string Filename: string (该图片在本地保存的文件名) downloaded: boolean (用于在下次抓取时判断是否需要重新下载) ------------------------------ o 新建一个unit,保存为ModalUnit.pas。再新建一个mdb数据库,取名为db1.mdb。 o 打开InstantObjects Modal Explorer, 单击select units按钮,选择刚刚建立的ModalUnit.pas o 在窗口空白处右击鼠标,选择New Class,开始创建我的第一个类 TBlogger (注:原来曾经用TUser做类名,结果出了一个古怪的select语句错误,原来是和保留字冲突了,所以我取名为TBlogger。) o 如图填写好TBlogger的属性后,选择Attributes页片,增加各项属性。因为还没有建立TArticle类,所以暂时先不设置它的Articles属性,只设一个BlogID即好。 o 现在我点击Build Database按钮,进入到创建数据库(Database Builder)的页面。右击窗体空白处,选择New|Ado Connection(最初我在安装IO的时候,选择了Ado做为处理要使用的broker,所以现在可以看到有相应的菜单项可用。)我命名为conn,然后右击conn,选择edit,进入Ado Connection的对话框,去掉Login Prompt前的对勾,并选择好自己要用到的数据库db1.mdb,点OK就可以了。然后,在Database Builder窗口中,单击Build按钮,就会自动为我建立好数据库的各个对应表了。 到了这里,暂时可以告一段落。双击建好的db1.mdb,检查是否如同所期望的那样,建立了表格。 如果没问题,继续回到前面的步骤中去,用类似方式,建立好TArticle和TPicture及其各个字段。要注意的是,TBlogger的Articles字段,以及TArticle的Pictures字段,它们的Storage Kind一栏应选External,表示将使用外部表保存相应属性。 (注:Pictures字段是后期我在程序中编码添加的,而非象其它字段那样,纯由IO自动生成。) 2.访问IO 建好数据库之后,下一步就是编码工作了。以下着重展示如何存取InstantObjects对象。(至于下载和解析网页的代码,这里从略。) Blogger表中保存的是新浪博客帐号,如果表中不存在相应记录,则创建之;如果已有,则提取出来。 blogger := Dm.GetAnUser('some_name'); ... ... function TDM.GetAnUser(const BlogID: string): TBlogger;
这里有一个问题,那就是当我访问TBlogger对象的时候,会出现一个异常: Error storing object TBlogger('C371D6060453A84E9E169B2EBB2ECB74'): "Field 'Articles' not found" 好蛋疼啊!为什么会这样,明明所有的内容都已创建好了,看上去一切正常的啊。。。 既然提示Articles字段不存在,那么就试着创建一个吧。我手工建立了一个string类型的Articles字段,再次运行程序。可以了。 我往Blogger对象中增加文章后,检查了一下Articles字段的内容,发现里面是一些二进制字符,以及新增文章的ID。可以想象,IO就是这样,向Articles字段中增加对Article表的关联的。 string类型有长度限制,我试着改为备注型,结果运行几次后,出现数据错误。估计是字段类型仍然没有选对。最后,我选择了二进制类型,一切OK。 我让程序在一开始的时候,就自动检查和创建相应的字段,以避免出错: procedure TDM.DataModuleCreate(Sender: TObject); (分析:我估计是IO对ADO的支持不是特别好,又或者ADO中,Access数据库缺乏某些关键特性,造成Articles字段必须得手工添加。另外,IO替我自动创建的Blogger_Articles表和Article_Pictures表,始终没有看见有数据进入,一直都是空的。估计用bde或firebird等数据库,应该可以运行得正常些吧)
不管怎么说,我的程序最终运行成功了,数据存取正常。希望这是一个良好的开端,将来能带来更多编程上的便利。 -------------------- 后记:关于IQL IQL是Instant Query Language的简称,上网居然找不到它的语法说明。。。汗。。。 好在从Primer.dpr中找到一些示例: All contacts: SELECT * FROM ANY TContact All employees: SELECT * FROM TPerson WHERE Employer.Name <> "" All employers:SELECT DISTINCT Employer FROM TPerson Employees at customers: SELECT * FROM TPerson WHERE Employer.Category.Name = "Customer" ORDER BY Name My friends: SELECT * FROM TPerson WHERE Category.Name = "Friend" Contact from Alabama: SELECT * FROM ANY TContact WHERE City = "Alabama" ORDER BY Name Corporations ordered descending by city: SELECT * FROM TCompany WHERE Name LIKE "%Corp%" ORDER BY City DESC Employees from same city as their employer: SELECT * FROM TPerson WHERE City = Employer.City 如果有朋友有更其它资料希望能在这里交流一下。 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论