Caché Objects | 第六章 | 定义数据类型类(DTC)

目录

  • 一、DTC概述
    • 1.1 DTC功能
    • 1.2 DTC与其他类的区别
    • 1.3 属性(Property)方法及工作原理
    • 1.4 数据格式
    • 1.5 DTC中的参数
  • 二、定义DTC
    • 2.1 基于现有DTC
    • 2.2 完全自定义DTC
  • 三、在DTC中定义类方法
  • 四、在DTC中定义实例方法
    • 4.1 案例

数据类型类(Data Type Classes):用作对象类中文本属性的类型。本文中,简写为 DTC

一、DTC概述

1.1 DTC功能

DTC提供以下功能:

  • 它们通过提供 SQL 逻辑操作、客户端数据类型 和 转换信息 来提供 SQL、ODBC、ActiveX 和 Java 互操作性。
  • 它们为文本数据值提供验证,您可以使用DTC类参数扩展自定义这些值。
  • 它们管理文本数据的存储(在磁盘上)、逻辑(在内存中)和显示格式的转换。

有关编译器如何使用DTC属性生成代码的信息,请参阅“使用和重写属性方法”一章。

1.2 DTC与其他类的区别

DTC在许多方面与其他类不同:

  • 它们不能单独实例化或存储
  • 它们不能包含属性
  • 它们支持一组特定的方法(称为数据类型接口)。

1.3 属性(Property)方法及工作原理

Class Datatypes.Container Extends %RegisteredObject
{

Property P1 As %String;

Property P2 As %Integer;

Property P3 As %Boolean;

}

这里,我们称Datatypes.Container容器类

当您向类添加文本属性编译该类时,Caché 会向该类添加属性方法。属性方法控制容器类如何处理这些属性的数据。该系统的工作原理如下:

  • 每个DTS都提供了一组方法,更具体地说是方法生成器Caché 在编译使用它们的类时会使用这些方法。方法生成器是生成自己的运行时代码的方法。
    在这里显示的示例中,当我们编译数据Datatypes.Container类时,编译器使用 %String%Integer%BooleanDTS的方法生成器。这些方法生成器为每个属性创建方法,并将这些方法添加到容器类中。如上所述,这些方法称为属性方法。它们的名称以它们所适用的属性的名称开头。例如,对于 P1 属性,编译器会生成 P1IsValid()P1Normalize()P1LogicalToDisplay()P1ToDisplayToLogical() 等方法。
  • 容器类在处理过程中的自动调用属性方法。例如,当您为上面所示的类的实例调用 %ValidateObject() 实例方法时,该方法会依次调用 P1IsValid()P2IsValid()P3IsValid() — 也就是说,它调用 IsValid()方法。
  • 再举一个例子,如果容器类是持久类,并且您使用 Caché SQL 访问关联表中的所有字段,并且 SQL 运行时模式是 ODBC,则 Caché 会为每个属性调用 LogicalToODBC() 方法,以便查询以 ODBC 格式返回结果。

请注意,属性方法类定义中不可见。

1.4 数据格式

许多属性方法将数据从一种格式转换为另一种格式,例如,在以人类可读的格式显示数据或通过 ODBC 访问数据时。格式为:

  • 显示 — 可以输入和显示数据的格式。例如,“1998 年 4 月 3 日”或“1977 年 11 月 23 日”形式的日期。
  • 逻辑 — 数据的内存格式,即执行操作所依据的格式。虽然日期具有上述显示格式,但其逻辑格式为整数;对于上述示例日期,其逻辑格式的值分别为 57436 和 50000。
  • 存储 — 数据的磁盘格式 — 将数据存储到数据库的格式。通常,这与逻辑格式相同。
  • ODBC — 可通过ODBC或JDBC呈现数据的格式。当数据向 ODBC/SQL 公开时,使用此格式。可用的格式与 ODBC 定义的格式相对应。
  • XSD — SOAP 编码格式。导出到 XML 或从 XML 导入时,将使用此格式。这仅适用于启用 XML 的类。

1.5 DTC中的参数

类参数在与DTC一起使用时具有特殊行为。对于DTC,类参数用于提供一种基于数据类型自定义任何属性行为的方法。
例如,%Integer DTC 具有一个类参数 MAXVAL,该参数指定 %Integer 类型属性的最大有效值。如果定义具有属性 NumKids 的类,如下所示:

Property NumKids As %Integer(MAXVAL=10);

这将指定 NumKids 属性的 %Integer 类的 MAXVAL 参数将设置为 10。

在内部,其工作原理如下:

  • 标准DTC的验证方法都作为方法生成器实现,并使用其各种类参数来控制这些验证方法的生成。
  • 在此示例中,此属性定义为 NumKidsIsValidDT() 方法生成内容,该方法测试 NumKids 的值是否超过 10。如果不使用类参数,创建此功能将需要定义IntegerLessThanTen类。

二、定义DTC

2.1 基于现有DTC

若要轻松定义DTC,请首先确定符合您需求的现有DTC, 然后创建此类的子类。在您的子类中:

  • 为关键字 SqlCategoryClientDataTypeOdbcType 指定合适的值。
  • 根据需要覆盖任何类参数。例如,可以重写 MAXLEN 参数,以便该属性没有长度限制。
    如果需要,还可以添加自己的类参数。
  • 根据需要重写DTC方法。在实现中,根据需要引用此类的参数。

2.2 完全自定义DTC

如果数据类型类不基于现有数据类型类,请确保将 [ ClassType=datatype ] 添加到类定义中。如果将类基于另一个数据类型类,则不需要此声明。

三、在DTC中定义类方法

根据您的需要,您应该在DTC中定义以下部分或全部类方法:

  • IsValid() — 执行属性数据的验证,如果适用,请使用属性参数。如前所述,任何对象类的 %ValidateObject() 实例方法都会为每个属性调用 IsValid() 方法。此方法具有以下签名, 其中 %val 是要验证的值。如果值无效,此方法应返回错误状态,否则应返回 $$$OK
ClassMethod IsValid(%val) As %Status 
  • Normalize() — 将属性的数据转换为标准形式或格式。任何对象类的 %NormalizeObject() 实例方法都会为每个属性调用 Normalize() 方法。此方法具有以下签名, 其中 %val 是要验证的值,Type 是合适的类型类。
ClassMethod Normalize(%val) As Type 
  • DisplayToLogical() — 将显示值转换为逻辑值。
ClassMethod DisplayToLogical(%val) As Type 
  • LogicalToDisplay() — 将逻辑值转换为显示值。
  • LogicalToOdbc() — 将逻辑值转换为 ODBC 值。
    请注意,ODBC 值必须与数据类型类的 OdbcType class 关键字指定的 ODBC 类型一致。
    LogicalToStorage() — 将逻辑值转换为存储值。
  • LogicalToXSD() — 将逻辑值转换为适当的 SOAP 编码值。
  • OdbcToLogical() — 将 ODBC 值转换为逻辑值。
  • StorageToLogical() — 将数据库存储值转换为逻辑值。
  • XSDToLogical() — 将 SOAP 编码的值转换为逻辑值。

如果DTC中包括 DISPLAYLISTVALUELIST 参数,则这些方法必须首先检查这些类参数是否存在,并包含用于处理这些列表的代码(如果存在)。其他方法的逻辑与此类似。

在大多数情况下,其中许多方法都是方法生成器。示例如下:

ClassMethod LogicalToDate(%val As %MV.Date) As %Library.Date [ CodeMode = expression, ServerOnly = 1 ]
{
$s(%val="":"",1:%val+46385)
}

注意:数据格式和转换方法不能包含嵌入式 SQL。如果需要在此逻辑中调用嵌入式 SQL,则可以将嵌入式 SQL 放在单独的例程中,该方法可以调用此例程。

四、在DTC中定义实例方法

还可以将实例方法添加到DTC

  • %val : 方法中可以使用变量 %val,该变量包含属性的当前值
  • 编译器使用这些方法在使用DTC的任何类中生成关联的属性方法

4.1 案例

例如,自定义DTC:Demo.Object.MyDate

Class Demo.Object.MyDate Extends %Date
{

Method ToMyDate() As %String [ CodeMode = expression ]
{
	$ZDate(%val,3)
}

}

定义一个Person类,添加属性DOB ,并设置其数据类型为刚自定义的MyDate

Class Demo.Object.Person Extends %RegisteredObject
{

Property DOB As MyDate;

}

底下,进行测试

 s instance=##class(QP.Object.Car).%New()
 s instance.DOB=+$h
 w instance.DOBToMyDate(),!

// 输出
2023-12-29

你可能感兴趣的:(Caché,Objects,Caché,Caché,Objects)