文章目录
-
第二十二章 Caché 定义数据类型类 - 数据类型类概述
- 定义数据类型类
- 在数据类型类中定义类方法
- 在数据类型类中定义实例方法
数据类型类的用途是用作对象类中的文本属性的类型。数据类型类提供以下功能:
-
它们通过提供SQL逻辑操作、客户端数据类型和转换信息来提供SQL、ODBC、ActiveX和Java互操作性。
-
它们为文字数据值提供验证,可以使用数据类型类参数对其进行扩展或自定义。
-
它们管理文字数据的存储(在磁盘上)、逻辑(在内存中)和显示格式的转换。
数据类型类在许多方面与其他类不同:
-
它们不能独立实例化或存储。
-
它们不能包含属性。
-
它们支持一组特定的方法(称为数据类型接口),如下所述。
由于了解一些内部细节很有用,因此本节简要讨论数据类型类的工作方式。
如前所述,数据类型类的用途是用作属性的类型,特别是在扩展核心对象类之一的类中。下面显示了一个具有三个特性的样例对象类。每个属性都使用一个数据类型类作为其类型。
Class Datatypes.Container Extends %RegisteredObject
{
Property P1 As %String;
Property P2 As %Integer;
Property P3 As %Boolean;
}
属性方法
向类添加文本属性并编译该类时,caché会向该类添加属性方法。作为参考,让我们使用术语容器类来指代包含属性的类。属性方法控制容器类如何处理这些属性的数据。
该系统的工作方式如下:
- 每个数据类型类都提供一组方法,更具体地说是方法生成器,在编译使用它们的类时,Caché会使用这些方法方法生成器是一种生成自己的运行时代码的方法。
在这里显示的示例中,当我们编译Datatypes.Container时,编译器使用%String、%Integer和%Boolean数据类型类的方法生成器。这些方法生成器为每个属性创建方法,并将这些方法添加到容器类。如上所述,这些方法称为属性方法。它们的名称以它们所应用的属性的名称开头。例如,对于P1属性,编译器生成诸如P1IsValid()、P1Normalize()、P1LogicalToDisplay()、P1ToDisplayToLogical()等方法。
- 容器类在处理过程中的适当位置自动调用属性方法。例如,当为上面显示的类的实例调用%ValidateObject()实例方法时,该方法依次调用P1IsValid()、P2IsValid()和P3IsValid()-也就是说,它为每个属性调用IsValid()方法。再举一个例子,如果容器类是持久化的,并且使用CachéSQL访问关联表中的所有字段,并且SQL运行时模式是ODBC,则Caché将为每个属性调用LogicalToODBC()方法,以便查询以ODBC格式返回结果。
请注意,属性方法在类定义中不可见。
数据格式
许多属性方法将数据从一种格式转换为另一种格式,例如,当以人们可读的格式显示数据或通过ODBC访问数据时。
格式为:
- Display 可以输入和显示数据的格式。例如,“April 3, 1998”或“23 November, 1977”形式的日期。
- Logical 内存中的数据格式,这是要对其执行操作的格式。虽然日期的显示格式如上所述,但它们的逻辑格式是整数;对于上面的示例日期,它们的逻辑格式值分别是57436和50000。
- Storage 数据的磁盘格式-数据存储到数据库的格式。通常,这与逻辑格式相同。
- ODBC 可以通过ODBC或JDBC呈现数据的格式。此格式在向ODBC/SQL公开数据时使用。可用的格式与ODBC定义的格式相对应。
- XSD SOAP编码格式。导出为XML或从XML导入时使用此格式。这仅适用于启用XML的类。
数据类型类中的参数
类参数在与数据类型类一起使用时具有特殊行为。对于数据类型类,类参数用于提供一种基于数据类型自定义任何属性行为的方法。
例如,%Integer数据类型类有一个类参数MAXVAL,它指定%Integer类型的属性的最大有效值。如果使用属性NumKids定义类,如下所示:
Property NumKids As %Integer(MAXVAL=10);
这指定NumKids属性的%Integer类的MAXVAL参数将设置为10。
在内部,这是这样工作的:标准数据类型类的验证方法都实现为方法生成器,并使用它们的各种类参数来控制这些验证方法的生成。
在此示例中,此属性定义为NumKidsIsValidDT()方法生成内容,该方法测试NumKidsIsValidDT()的值是否超过10。如果不使用类参数,创建此功能将需要定义IntegerLessThanTen类。
定义数据类型类若要定义数据类型类,请首先标识最接近你需要的现有数据类型类。创建此类的子类。在的子类中:
- 为关键字SqlCategory、ClientDataType和OdbcType指定合适的值。
- 根据需要重写任何类参数。例如,可以替代MAXLEN参数,以使特性没有长度限制。
如果需要,还可以添加自己的类参数。
- 根据需要重写数据类型类的方法。在的实现中,请根据需要引用该类的参数。
如果数据类型类不是基于现有的数据类型类,请确保将[ClassType=DataType]添加到类定义中。如果类基于另一个数据类型类,则不需要此声明。
在数据类型类中定义类方法根据需要,应该在数据类型类中定义以下部分或全部类方法:
- IsValid() 在适当的情况下使用特性参数执行特性的数据验证。如前所述,任何Object类的%ValidateObject()实例方法都会为每个属性调用IsValid()方法。
ClassMethod IsValid(%val) As %Status
其中%val是要验证的值。如果值无效,此方法应返回错误状态,否则应返回$OK。
注意:Caché中的标准做法是不调用空值的验证逻辑。
- Normalize() 将属性的数据转换为标准表单或格式。任何Object类的%NormalizeObject()实例方法都会为每个属性调用Normalize()方法。
ClassMethod Normalize(%val) As Type
翻译:
其中%val是要验证的值,Type是合适的类型类。
- DisplayToLogical() 将显示值转换为逻辑值。
ClassMethod DisplayToLogical(%val) As Type
其中%val是要转换的值,Type是合适的类型类。
其他格式转换方法具有相同的形式。
- LogicalToDisplay() —将逻辑值转换为显示值。
- LogicalToOdbc() — 将逻辑值转换为ODBC值。
请注意,ODBC值必须与数据类型类的 ODBC Type类关键字指定的ODBC类型一致。
- LogicalToStorage() — 将逻辑值转换为存储值。
- LogicalToXSD() — 将逻辑值转换为适当的SOAP编码值。
- OdbcToLogical() — 将ODBC值转换为逻辑值。
- StorageToLogical() — 将数据库存储值转换为逻辑值。
- XSDToLogical() — 将SOAP编码值转换为逻辑值。
如果数据类型类包括DISPLAYLIST和VALUELIST参数,则这些方法必须首先检查是否存在这些类参数,并包含处理这些列表的代码。其他方法的逻辑与此类似。
在大多数情况下,这些方法中的许多都是方法生成器。
例如:
ClassMethod LogicalToDate(%val As %MV.Date) As %Library.Date [ CodeMode = expression, ServerOnly = 1 ]
{
$s(%val="":"",1:%val+46385)
}
注意:请注意,数据格式和转换方法不能包含嵌入式SQL。如果需要在此逻辑中调用嵌入式SQL,则可以将嵌入式SQL放在单独的例程中,该方法可以调用此例程。
在数据类型类中定义实例方法还可以向数据类型类添加实例方法,这些方法可以使用变量%val,该变量包含属性的当前值。编译器使用它们在使用数据类型类的任何类中生成关联的属性方法。
例如,考虑以下示例数据类型类:
Class Datatypes.MyDate Extends %Date
{
Method ToMyDate() As %String [ CodeMode = expression ]
{
$ZDate(%val,3)
}
}
假设我们有另一个类,如下所示:
Class Datatypes.Container Extends %Persistent
{
Property DOB As Datatypes.MyDate;
}
当我们编译这些类时,Caché会将实例方法DOBToMyDate()添加到容器类中。然后,当我们创建CONTAINER类的实例时,我们可以调用此方法。例如:
SAMPLES>set instance=##class(Datatypes.Container).%New()
SAMPLES>set instance.DOB=+$H
SAMPLES>write instance.DOBToMyDate()
30/10/2014