硕鼠的博客站

范路的博客主站,时而会发些东西。

Category : DevCo

下面让我们来分析以下VCL for PHP的基本结构,李维在作 Demo的时候最喜欢拿出来炫的就是Google Map VCL,你们能够想像得出来这个组件一共有多少行代码吗?

不到100行,是不是吓到了?你有可能编写很少的代码,就可以开发一共非常漂亮的组件,并且开始你自己的软件创业之路。

下面让我们来看一下这个组件的源代码:

<?php

        //Includes

        require_once("vcl/vcl.inc.php");

 

        use_unit("controls.inc.php");

 

        //Class definition

        class GoogleMap extends Control

        {

            function __construct($aowner = null)

            {

                parent::__construct($aowner);

            }

 

            private $_mapskey="ABQIAAAAQlQ8ZvigZnDc1z7MTEuUQxTJO8fVsnY3pyCJC531oZiosu_8phSnTlxi08R1_58Gfdyd9NUJdyES5w";

 

            function getMapsKey() { return $this->_mapskey; }

            function setMapsKey($value) { $this->_mapskey=$value; }

            function defaultMapsKey() { return "ABQIAAAAQlQ8ZvigZnDc1z7MTEuUQxTJO8fVsnY3pyCJC531oZiosu_8phSnTlxi08R1_58Gfdyd9NUJdyES5w"; }

 

            private $_address="Scotts Valley, CA";

 

            function getAddress() { return $this->_address; }

            function setAddress($value) { $this->_address=$value; }

            function defaultAddress() { return "Scotts Valley, CA"; }

 

 

 

            function dumpHeaderCode()

            {

?>

    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key= <?php echo $this->MapsKey; ?>"

      type="text/javascript"></script>

    <script type="text/javascript">

    //<![CDATA[

    function <?php echo $this->Name; ?>load()

    {

      if (GBrowserIsCompatible())

      {

        var map = new GMap2(document.getElementById("<?php echo $this->Name; ?>_div"));

        map.addControl(new GLargeMapControl());

        map.addControl(new GScaleControl());

        map.addControl(new GMapTypeControl());

 

        var geocoder = new GClientGeocoder();

 

        var address="<?php echo $this->Address; ?>";

 

        geocoder.getLatLng (address,

 

        function(point)

        {

                if (!point)

                {

                        alert(address + " not found");

                }

                else

                {

                        map.setCenter(point, 13);

                        var marker = new GMarker(point);

                        map.addOverlay(marker);

                        marker.openInfoWindowHtml(address);

                }

        }

        );

      }

   }

    //]]>

    </script>

<?php

            }

 

            function dumpContents()

            {

                echo "<div id="".$this->Name."_div" style="width: ".$this->Width."px; height: ".$this->Height."px"></div>";

?>

    <script type="text/javascript">

    <?php echo $this->Name; ?>load();

    </script>

<?php

            }

        }

 

?>

 

连空行都算上一共84行。我就不讲解这段代码了,我想不管你是什么语言的程序员, DelphiPHPJava C++C#JavaScript等等等等,你应该都能够读懂上面的几十行代码。

看看,这是多么容易的一件事啊,你也能的。

 

如果你希望能够进入这个行业,那么我给大家指几个方向,供大家参考。在早期,这个领域还是一片空白的时候,大家可以试着从这些方向下手。

第一、    使用现有组件进行一些扩展,完成一些更加具体的功能:

下面这个例子是LabeledEdit组件,将一个 Label和一个Edit组合起来,完成一个完整的功能。

class SubLabel extends Persistent

{

        protected $_caption = "";

 

        function assignTo($dest)

        {

                $dest->_caption=$this->_caption;

        }

 

        /**

         * Specifies the caption used in the label

         *

         * @return string

         */

        protected function readCaption()           { return $this->_caption; }

        protected function writeCaption($value)    { $this->_caption=$value; }

        function defaultCaption()                  { return ""; }

 

        // publish properties

        function getCaption()           { return $this->readCaption(); }

        function setCaption($value)     { $this->writeCaption($value); }

}

 

class CustomLabeledEdit extends CustomTextField

{

        protected $_lblname = "";

 

        protected $_edtlabel=null;

        protected $_lblspacing = 3;

        protected $_lblposition = lpAbove;

        protected $_text = "";

 

        protected function CalculateEditorRect()

        {

                switch ($this->_lblposition)

                {

                  case lpBelow:

                        $y = 0;

                        break;

                  default: // lpAbove:

                        $y = 14 + $this->_lblspacing;

                        break;

                }

                return array(0, $y, $this->Width, $this->Height - 14 - $this->_lblspacing);

        }

 

        protected function dumpExtraControlCode()

        {

                $eh = $this->Height - 14 - $this->_lblspacing;

                switch ($this->_lblposition)

                {

                  case lpBelow:

                        $y = $eh;

                        break;

                  default: // lpAbove:

                        $y = 0;

                        break;

                }

 

                $this->_lblname = $this->Name . "_Lbl";

 

                echo "  var $this->_lblname = new qx.ui.basic.Atom("" . $this->_edtlabel->Caption . "");n"

                   . "  $this->_lblname.setLeft(0);n"

                   . "  $this->_lblname.setTop($y);n"

                   . "  $this->_lblname.setWidth($this->Width);n"

                   . "  $this->_lblname.setHorizontalChildrenAlign("left");n";

 

                if (($this->Visible) || (($this->ControlState & csDesigning)==csDesigning))

                      { $visible="true"; }

                else  { $visible="false"; };

                echo "  $this->_lblname.setVisibility($visible);n"

                   . "  inline_div.add($this->_lblname);n";

        }

 

        function __construct($aowner = null)

        {

                //Calls inherited constructor

                parent::__construct($aowner);

 

                $this->_edtlabel = new SubLabel();

                $this->Width = 121;

                $this->Height = 34;

        }

 

        function setName($value)

        {

                $oldname=$this->_name;

                parent::setName($value);

 

                //Sets the caption if not already changed

                if ($this->_edtlabel->Caption == $oldname)

                {

                        $this->_edtlabel->Caption = $this->Name;

                }

        }

 

        /**

         * Use EditLabel to work with the label that is associated with this

         * labeled edit control. Use this label�s properties to specify the

         * caption that appears on the label.

         */

        protected function readEditLabel()              { return $this->_edtlabel; }

        protected function writeEditLabel($value)       { if (is_object($value)) $this->_edtlabel=$value; }

        /**

         * Specifies the position of the label relative to the edit control.

         *

         * @return enum (lpAbove, lpBelow)

         */

        protected function readLabelPosition()          { return $this->_lblposition; }

        protected function writeLabelPosition($value)   { $this->_lblposition=$value; }

        function defaultLabelPosition()     { return lpAbove; }

        /**

         * Specifies the distance, in pixels, between the label and the edit region.

         *

         * @return integer

         */

        protected function readLabelSpacing()           { return $this->_lblspacing; }

        protected function writeLabelSpacing($value)    { $this->_lblspacing=$value; }

        function defaultLabelSpacing()      { return 3; }

}

 

class LabeledEdit extends CustomLabeledEdit

{

        //Publish common properties

        function getAlign()             { return $this->readAlign(); }

        function setAlign($value)       { $this->writeAlign($value); }

 

        //function getFont()              { return $this->readFont(); }

        //function setFont($value)        { $this->writeFont($value); }

 

        function getColor()             { return $this->readColor(); }

        function setColor($value)       { $this->writeColor($value); }

 

        function getEnabled()           { return $this->readEnabled(); }

        function setEnabled($value)     { $this->writeEnabled($value); }

 

        function getParentColor()       { return $this->readParentColor(); }

        function setParentColor($value) { $this->writeParentColor($value); }

 

        function getParentFont()        { return $this->readParentFont(); }

        function setParentFont($value)  { $this->writeParentFont($value); }

 

        function getParentShowHint()    { return $this->readParentShowHint(); }

        function setParentShowHint($value) { $this->writeParentShowHint($value); }

 

        function getPopupMenu()         { return $this->readPopupMenu(); }

        function setPopupMenu($value)   { $this->writePopupMenu($value); }

 

        function getShowHint()          { return $this->readShowHint(); }

        function setShowHint($value)    { $this->writeShowHint($value); }

 

        function getVisible()           { return $this->readVisible(); }

        function setVisible($value)     { $this->writeVisible($value); }

 

        //Publish Edit control properties

        function getBorderStyle()       { return $this->readBorderStyle();  }

        function setBorderStyle($value) { $this->writeBorderStyle($value);  }

 

        function getCharCase()          { return $this->readCharCase(); }

        function setCharCase($value)    { $this->writeCharCase($value); }

 

        function getDataField()         { return $this->readDataField(); }

        function setDataField($value)   { $this->writeDataField($value); }

 

        function getDataSource()        { return $this->readDataSource(); }

        function setDataSource($value)  { $this->writeDataSource($value); }

 

        function getIsPassword()        { return $this->readIsPassword(); }

        function setIsPassword($value)  { $this->writeIsPassword($value); }

 

        function getMaxLength()         { return $this->readMaxLength(); }

        function setMaxLength($value)   { $this->writeMaxLength($value); }

 

        function getReadOnly()          { return $this->readReadOnly(); }

        function setReadOnly($value)    { $this->writeReadOnly($value); }

 

        function getText()              { return $this->readText(); }

        function setText($value)        { $this->writeText($value); }

 

        // publish Common Events

        function getjsOnActivate()      { return $this->readjsOnActivate(); }

        function setjsOnActivate($value){ $this->writejsOnActivate($value); }

 

        function getjsOnDeActivate()    { return $this->readjsOnDeActivate(); }

        function setjsOnDeActivate($value) { $this->writejsOnDeActivate($value); }

 

        function getjsOnChange()        { return $this->readjsOnChange(); }

        function setjsOnChange($value)  { $this->writejsOnChange($value); }

 

        function getjsOnBlur()          { return $this->readjsOnBlur(); }

        function setjsOnBlur($value)    { $this->writejsOnBlur($value); }

 

        function getjsOnClick()         { return $this->readjsOnClick(); }

        function setjsOnClick($value)   { $this->writejsOnClick($value); }

 

        function getjsOnContextMenu()   { return $this->readjsOnContextMenu(); }

        function setjsOnContextMenu($value) { $this->writejsOnContextMenu($value); }

 

        function getjsOnDblClick()      { return $this->readjsOnDblClick(); }

        function setjsOnDblClick($value){ $this->writejsOnDblClick($value); }

 

        function getjsOnFocus()         { return $this->readjsOnFocus(); }

        function setjsOnFocus($value)   { $this->writejsOnFocus($value); }

 

        function getjsOnKeyDown()       { return $this->readjsOnKeyDown(); }

        function setjsOnKeyDown($value) { $this->writejsOnKeyDown($value); }

 

        function getjsOnKeyPress()      { return $this->readjsOnKeyPress(); }

        function setjsOnKeyPress($value){ $this->writejsOnKeyPress($value); }

 

        function getjsOnKeyUp()         { return $this->readjsOnKeyUp(); }

        function setjsOnKeyUp($value)   { $this->writejsOnKeyUp($value); }

 

        function getjsOnMouseDown()      { return $this->readjsOnMouseDown(); }

        function setjsOnMouseDown($value){ $this->writejsOnMouseDown($value); }

 

        function getjsOnMouseUp()       { return $this->readjsOnMouseUp(); }

        function setjsOnMouseUp($value) { $this->writejsOnMouseUp($value); }

 

        function getjsOnMouseMove()     { return $this->readjsOnMouseMove(); }

        function setjsOnMouseMove($value) { $this->writejsOnMouseMove($value); }

 

        function getjsOnMouseOut()      { return $this->readjsOnMouseOut(); }

        function setjsOnMouseOut($value) { $this->writejsOnMouseOut($value); }

 

        function getjsOnMouseOver()     { return $this->readjsOnMouseOver(); }

        function setjsOnMouseOver($value) { $this->writejsOnMouseOver($value); }

 

        // publish new properties

        function getEditLabel()             { return $this->readEditLabel(); }

        function setEditLabel($value)       { $this->writeEditLabel($value); }

 

        function getLabelPosition()         { return $this->readLabelPosition(); }

        function setLabelPosition($value)   { $this->writeLabelPosition($value); }

 

        function getLabelSpacing()         { return $this->readLabelSpacing(); }

        function setLabelSpacing($value)   { $this->writeLabelSpacing($value); }

        // publish events

        function getOnClick()           { return $this->readOnClick(); }

        function setOnClick($value)     { $this->writeOnClick($value); }

}

第二、    结合JavaScript来做一些页面特效,这需要JavaScript 比较熟悉的人来完成。我向很多JavaScript程序员手里应该已经积攒了不少非常棒的代码,比如各种按钮、菜单等等。

第三、    结合一些提供特定服务的网站,例如Google Map,或者是图片交流方面的或者是提供一些特定信息的 WebServices网站,例如股票、金融、餐饮服务、新闻、天气、出行信息等内容,作一些能够提供特定信息的组件。这些组件可以从网站得到一些收入。

第四、    将现在比较流行的完整的开源代码拆开,封装成组件包。

第五、    GridReport Chart这三类组件在Delphi VCL里面是种类最丰富的,所以如果能够在这方面及早下手,肯定效果不错。

第六、    调用PHP基础函数,封装一些基础功能也是一个不错的选择,比如 phpinfo()就完全可以进行些方面的封装,FTP和各种文件操作封装的余地也很大。

第七、    编写一些特定的数据库连接和操作的组件应该有不错的应用前景。

第八、    结合Delphi或者是C++ 来编写一些PHP扩展,然后将去封装到VCL中,可以完成一些更强劲的的功能,也更容易让客户认同这些组件的价值。

第九、    编写完整的网站决绝方案,比如门户网站、BBS、商务网站等等。

 

我在这里只是启一个头儿,相信大家能够想出更多更有创意的点子来。

 

 

 

 

 

让我们一起来迎接新控件时代的到来吧!

 

CodeGear现在正在就C++Builder未来的开发走向问题,向全世界的开发人员征询意见和建议。截至到目前为止,中国地区的反馈数量非常的少。请大家尽量发动所有的相关程序员去填写调查问卷,千万不要到C++Builder发布的时候才发现这个产品不符合中国程序员的使用习惯或者是对于中国大的软件应用环境支持的不是很好等问题。

 

请大家一定要抓住这个难得的机会,让CodeGear公司的开发团队听到我们的声音。

 

请点击以下链接来提交您的意见:C++Builder 开发者调查问卷 2007 (简体中文)

IDE开发工具并发license设置方式

以前使用各种IDE工具,只用过个人版,到了Borland之后才知道还有网络版出售。个人版即大家通常使用的方式,每个人自己有一套开发工具,每个人的开发工具都必须购买单独的License(或者破解)。我们管这种License叫做Named License,即每一个License都有一个用户的名字,这个用户拥有这个License,并且可以使用这个License所许可的相应软件。网络版则是在局域或者广域网中设置一台License Server ,然后一次购买一批License,所有的到授权的用户都可以通过这个License Server的授权来使用他自己计算机上的软件。这种License我们叫做Concorrent(并发) License, 比如一个单位购买了10个JBuilder2007的Concorrent License,则该单位的局域网中最多可以有10个用户同时开机使用JBuilder2007,至于这10个用户具体是谁那就不是无所谓了。
前一段时间遇到了一个客户,他公司里面有十几个程序员都跳槽了。他们原来购买的一批JBuilder软件由于用户绑定,新来的程序员无法激活使用,如果他们使用Concorrent License的话就不会出现这种问题了。软件行业好像没有两班倒、三班倒的惯例,如果有的话则可以有两班到三班的程序员使用一批License,如果是国际团队的化可以通过时差来控制License的使用情况。所有的软件都是有激活次数限制的,具体的次数是各公司的机密,但是我们中国的软硬件环境比较复杂所以经常出现,在不长的时间里面,客户即将公司所购买的正版软件的次数激穿,造成软件报废。如果使用Concorrent License,只要License服务器不经常出问题,具体程序员的机器重新安装多少次都没有关系,也可以一个项目组用完之后另外一个项目组再用。总之Concorrent License有很多的优点,但是同时这种License的价格也相应的要比Named License贵一些,一般情况下Concorrent License的价格是Named License的两倍。各企业可以根据自己的需要进行选购。
 
下面来介绍一下Concorrent License的简单备置方法。
CodeGear产品可以使用两种不同的License服务器,一种是BLS(Borland License Server),另外一种是FLEXlm License Server,在订购Concorrent License产品的时候必须要指明具体要哪一种。如果你之使用CodeGear和Borland产品则建议使用BLS,因为设置起来比较简单,如果你公司内部还使用或者是计划其它公司的使用Concorrent License的软件,则最好选用FLEXlm,因为大多数提供Concorrent License的公司都支持FLEXlm,你可以使用一台License Server将公司内部不通品牌的软件产品进行统一的管理。两种License的价格是一样的。
下面我们分别介绍。
 
当一个客户订了一个产品的Concorrent License之后,CodeGear License管理中心会给这个客户去一封信(eMail),告诉用户一个网址和一套账号密码。用户可以在这个网址上下载BLS或者FLEXlm软件,这些软件都是支持不通平台的。然后用户需要使用邮件中所给的账号进行登陆,之后就可以下载License文件了,当然下载License文件之前网站后有一个表格要求用户填写,如果是BLS的话需要填写服务器的主机名,如果是FLEXlm的话则需要先在命令行中运行一个程序lmhostid.exe(我们这里所有的例子都按照windows平台来说,其它平台的用户自学能力和适应能力都很强,自己看英文说明书应该没有问题,所以我就不在这里啰嗦了),该程序会产生四组号码,随便挑一组填写到网站的表格中即可,这个步骤是让这个License和你运行License服务器的机器绑定。如果你更换了License服务器,或者是License服务器发生故障重新安装操作系统,则必须走一个非常复杂的流程重新申请License激活,而且还有可能申请不被批准,所以一定要选一台好一点的机器作为License Server,而且不要在上面安装其它程序,平时也不要让任何不相干的人接触这台机器。填完表格之后则可以下载License文件了。License文件一般是个ZIP打包的压缩包,里面保护三个文件:readme.txt(简单的英文使用说明)、concorrent_?????.slip(需要复制到每一台使用该软件的计算机的指定目录下的客户端使用许可文件)、server_?????.slip(BLS服务器端使用的License文件,如果你订购的是FLEXlm的话这个文件叫做license_??????.dat)。
concorrent_?????.slip放置的位置根据使用的软件不同而不同,具体情况如下:
  <Borland Enterprise Server>/license
  <Borland Deployment Op-Center>/license
  <C#Builder>/
  <C++BuilderX>/defaults
  <CaliberRM Server>/license
  <Delphi2005>/license
  <Delphi8>/
  <JBuilder2007>/jbuilder/eclipse/license
  <JBuilder2006>/license
  <JBuilder2005>/license
  <JBuilderX>/defaults
  <JBuilder9>/defaults
  <JBuilder8>/defaults
  <Optimizeit>/lib
  <Optimizeit2006>/license
  <Optimizeit ServerTrace3.0>/license
  <StarTeam Server>/license
  <Together 2006>/license
  <Together2005 VS.NET>/license
  <Together VS.NET>/defaults
  <Together CC>/bin
  <Together EC7.0>/license
  <Together EC6.3>/license
  <Together EC6.2>/
  <Together EC6.1>/
  <Together WS>/
再下一步就是设置服务器了,首先我们讲BLS,先将server_?????.slip复制到BLS安装目录下的conf子目录中,然后在这个子目录中创建一个叫做userlist-concorrent.txt的文件,这个文件中规定有哪些用户可以用哪些机器登陆到这个License Server上来申请软件的使用许可,这个许可的有效期是多长时间。
这个文件的初始的内容是这样的:
# This file specifies named users.
#
# Formats:
# user name, host name, identifier, off-line period
# user name, host name, product, sku, off-line period
#
# - user name: user's machine login name
# - host name: always '*' for named user licenses
# - identifier, product, sku: defined in readme_xxx.txt file(s) downloaded from
Borland's Hosting Web site
# - off-line period: a whole number of days (30 day max)
#
# Example: user with login 'pjohnson' is granted a license with a 7 day off-line
 period
#
#  pjohnson, *, 100_1_1, 7
#  pjohnson, *, 1008, 2, 7
然后我们加上:
luke, *, 100_0, 30
意思是luke这个用户可以在任意一台机器上使用100_0(即JBuilder2007)这个产品30天。
然后在BLS安装目录下bin目录中的运行
belise.bat start
启动Borland License Server,belise.bat有几个参数下面我们就常用的几个简单的解释一下:
start                 服务器启动
stop                  服务器停止
installService      安装windows服务
uninstallService  卸载windows服务
 
如果将BLS安装成了windows服务,则每次计算机启动就会自动启动BLS不需要人为的干预,所以建议大家设置好之后将它安装成Windows服务。
现在所有的工作都完成了,可以使用客户端上的软件了。另外要提的一点是目前BLS的版本是BLS4,这个版本运行的时候必须要有JDK1.4(JRE不行),所以在安装BLS4之前一定要先确认JDK1.4的位置,在安装的过程中安装程序会询问的。在License服务器使用的过程中,要保证JDK1.4的可用,如果JDK1.4发生了问题,或者是改变了位置则BLS无法正常启动。
 
下面来说一下FLEXlm的使用方式:
FLEXlm不需要安装,解压缩到硬盘就可以了,然后将License压缩包中的license_?????.dat也复制到这个目录下,如果你已经有了FLEXlm服务器则把从Borland下载的FLEXlm压缩包中的borland.exe文件复制到原来FLEXlm文件夹中,然后执行命令
lmgrd.exe -z -c license_?????.dat -l flex.log
就可以使用了。
然后用
lmremove.exe -c license_?????.dat
就可以把服务器停下来。另外用lmtools.exe可以将FLEXlm配制成windows服务,这个程序有windows界面,比较简单我就不细讲了。
FLEXlm的功能是非常强的,它可以同时配置多种产品的License服务器,也可以将已经配置成功的License导出一部分或全部,然后再在其它的服务器上导入,比如你公司有一个小组要进行封闭式开发,那么你就可以将这个小组要用到的软件License导出去,让这个封闭式开发的小组布置一台独立的License服务器,开发完成之后,再导回来。这些高级功能我这里就不详细介绍了,如果大家真要用到,再看手册吧。

CodeGear的网站已经投入使用了

CodeGear的网站已经投入使用了,希望有兴趣的人上去看看。
 

Interbase2007试用版可以下载了

Interbase2007的试用版现在已经可以下载了,请有兴趣的朋友下载了试一下。
 

最忙乱的两星期

我和李维大师一起完成了JBuilder2007和Interbase2007的5站发布会。
北京和上海的朋友见到了李维大师和我,其中李维大师做了JBuilder2007新品发布精彩演讲和超酷例子,我给大家带来的是Interbase2007的介绍演讲和批量数据更新的例子。因为李维大师还要赶回台湾参加台湾的JBuilder2007发布会,所以大连、深圳和香港的演讲和Demo是由我一个人独立完成的。
总体的感觉很好,大家还是非常热情的。感觉上北京的客户最热情,上海的客户最深沉,大连的客户最准时(离开场10分钟了,只有一个人到场,当时把我吓坏了。但是开场的时候所有邀请的客户都到达了,一个也不少),深圳的客户到场最早(很多客户非常早就到场了,演讲开始之后一直有人陆续到场),香港的人数最少(很多软件开发团队都转移到大陆了)。关于到场时间的问题,我想主要是和该城市的交通环境有关。具体演讲中的例子我会在过几天整理以后发布到上来,但是我只有我自己的例子,李维老师的例子我想在他的Blog上应该可以看到。
Demo列表:
Interbase2007批量更新演示
可视化EJB3编程演示
可视化JPA编程演示
 
另外演讲稿如何上传到MSN Live Spaces我还没有搞明白,如果需要可以留eMail,我发给你们。

购买Borland® InterBase® 2007的五大理由

持久保护数据,维持高可用性

为进一步提高可用性,InterBase® 2007提供了故障保护的新功能,并增加了灾难恢复的手段,如用于短期恢复的日志和在硬件系统出现故障后用于长期恢复的日志存档。此外,InterBase® 2007还引入了数据库文件的Online Dump以及从存档中进行实时恢复。

可移动、国际化、跨平台的数据库允许进一步扩展,方便灵活

InterBase® 2007被证明可在不改动Windows®, Linux and Solaris™的情况下顺利运行。它可在多种平台上进行布署而无须重新编码。InterBase® 2007可在各个平台之间移动,也可在InterBase® 2007桌面版和服务器版之间移动,布署方便灵活。此外,InterBase® 2007支持国际字符集,如最新的UnicodeUTF-8UCS2,便于国际布署。

适应不通的硬件平台,达到最高的数据库性能

InterBase 2007是现有最快的本地数据库之一。通过支持SMP(对称多处理器),InterBase 2007能够适应多种CPU,包括多核CPU。在多个方面还进行了性能提高和最优化,如批量更新、查询最优化以及通过日志实现的OLTP改进。InterBase 2007执行多代结构,能够提供独一无二的版本化,因此交易处理用户和决策支持用户能够同时享受数据的高可用性。在同一机器上同时支持多实例能够实现应用隔离和负载均衡。

嵌入布署零维护

InterBase 2007安装简单,能够自动进行灾难恢复,并提供丰富的配置API接口以便于嵌入应用。最适于那些需要较小内存和磁盘空间却又不能因此影响复杂功能实现强劲关键业务的应用,如ISVsOEMs以及VARs。与其它企业数据库不同,InterBase 2007不需要昂贵的支持和维护,基本上可以做到零维护。

为开发人员而设计

使用Borland Developer Studio 2006,包括Delphi® Delphi for .NET C++Builder® C#Builder® Borland JBuilder® 2006 以及其它工具的开发人员可以通过ODBC JDBC ADO.NET,和IBX支持多个标准数据库连接选项。业务监控工具能为开发人员提供粒状数据库控件用以查看、开始、停止或回滚交易、处理和查询。InterBase采用 SQL92标准,能够满足开发人员对SQL数据库的任何要求:触发器,存储过程,视图以及一些先进的概念如域和事件预警。

下周西安进行BDS2006和Interbase2007应用的研讨会

下周要到西安进行Interbase2007的技术研讨会。
不知道国内是否还有Interbase的使用者。Interbase是一种非常棒的数据库产品,速度奇快,在同样的硬件环境下速度比MSSQL快很多。在2007版中增加了很多新的功能,解决了很多Interbase以前的问题。
感觉最棒的两个功能是在线增量备份和批量更新。
在线增量备份,就像名字上写的那样,可以在基本不影响前台工作的前提下比较快速的将数据库进行备份。我作了一个实验,当第一次对一个1.5G的数据库进行online dump(增量备份也叫在线倾倒)的时候用了40分钟(不好意思,机器比较老旧),然后向数据库里面插入了一万条记录,然后再执行相同的命令,两分钟完成。在Dump的同时进行的数据库操作会比平时慢一些,但是还是可以接受的。当数据库发生问题的时候,可以直接将Dump的文件作为Interbase数据库进行加载,基本上可以做到无缝实时恢复。有了这个技术基本上可以保证我们的程序每30分钟到60分钟进行一次增量备份。
增量备份的实现方法对于Delphi程序员来说主要有两种:
1、命令行:
gbak -d dbtest.gdb dbtest.dmp -user sysdba -pass masterkey
第一次执行这个命令的时候会进行一次完整的备份。以后每次执行就进行增量备份。
如果键入
gbak -d dbtest.gdb dbtest.dmp -user sysdba -pass masterkey -ov
则进行一次强制的完整备份。
2、通过IBX组件实现同样的功能:
Interbase2007提供了新的IBX组件,其中IBDatabase支持增量备份。
首先在IBDatabase1中设置好数据库连接,然后执行下面的这个语句完整增量备份动作(建议在后台线程里面执行):
IBDatabase1.OnlineDump(['dbtest.dmp'], [], false, false);
这个函数一共有四个参数,第一个是dump文件数组,可以有多个dump文件;第二个是文件容量数组,如果有多个dump文件,你就必须告诉Interbase每个文件的容量是多大,当前面的文件满了,才开始写后面的文件,最后一个文件的容量一般不写;第三个参数是确定是进行增量备份还是全备份,如果是true的话就是全备份,所以我们使用false进行增量备份;第四个参数是是否overwrite整个dump文件,如果是true的话,就相当于在命令行的时候加了'-ov'这个参数。
批量更新准许我们把一批SQL语句(insert、update、delete)一起提交到数据库服务器中去,统一执行。我试过了,插入一千条记录所用时间基本上是逐条插入的三分之一。
应用方法:
使用IBScript组件,
IBScript1.Script.Clear;
IBScript1.Script.Add('Batch Start;');
IBScript1.Script.Add('Insert .......;');
...
...
...
IBScript1.script.Add('Batch Execute;');
IBScript1.ExecuteScript;
注意事项:开始的第一句是Batch Start ,最后一句是Batch Execute ,每句都以分号结尾, 里面的语句不要太多,我试过2000条没什么问题,但是我的字段比较少,所以建议大家控制在500~1000条之间。
 
先写这些,其它的新功能我正在研究,等登过一段时间在和大家分享。

BDS推出了最新的Hotfix

DevCo在收集了一批客户所提出的意见之后,推出了最新的Hotfix9。而且将所有的Hotfix打包在了一起,这个程序会自动检查客户原来是否安装过某个特定版本的Hotfix,如果没有的话就会安装上去。
欢迎大家去下载试用。
另外,大家也可以把网站上面提供的Free Tools下载下来试试。很有意思的。

惨遭AJAX折磨

最近在学习AJAX,首先从基础学起,使用Peloton(JBuilder for Eclipse)进行最基础的JavaScript编程,但是由于JavaScript的变量没有类型、无法调试。一旦有个别的地方出现拼写错误就很难找出来,后来改用Firefox的JavaScript控制台功能,终于决绝了JavaScript的问题。
后来到Delphi2006里面进行.NET测试,直接使用MagicAjax(www.magicajax.com)组件,但是怎么试都不对,被活活的折磨了两天。我把<add name="MagicAjax" type="MagicAjax.MagicAjaxModule, MagicAjax" />添加到了Web.config里面,结果系统告诉我找不到magicajax.dll文件,如果我把这个文件复制到bin目录下,系统有显示这个文件已经存在了无法再次加载。最后在问了香港的Terence之后得知,问题可能出在我使用的cassini上,换成IIS一试果然没有问题了。
我活活的被Cassini折磨了两天。惨啊。希望大家引以为戒,不要犯同样的错误。
Close Bitnami banner
Bitnami