Creating Summarization Classes

This section describes how to create import-time summarization classes to aggregate data from a base class.

The purpose of a summarization class is to perform load-time aggregation based on different dimensions and to calculate meaningful measure data in an efficient way. The following list contains the specifications for a summarization class. A summarization class must:

  • Be a class defined in the Data Warehouse schema.
  • Specify a base class whose data will be aggregated.
  • Contain one or more class members marked as dimensions or measures.
  • Contain dimensions that specify expressions indicating how the dimensions should be extracted from the base class.
  • Contain measures that specify expressions indicating how the measure should be computed from the base class.
  • Have a key definition that consists of all the dimension members.

The dimension expressions for the summarization class must follow these guidelines:

  • All expressions must have the following syntax for each dimension expression in the summarization class:

    dimension-expr    := date-expr | member-val-expr | uri-expr
    date-expr          := datepart(date-selector, a member in the base class       
        of type datetime)
    date-selector      := yy | yyyy | yyyyq | yyyymm | 
        yyyymmdd | yyyymmddhh | yyyymmddhhmi |
        mm | hh | mi | ss | ms | q | yd | wd | mq 
    member-val-expr   := member-name
    uri-expr            := uripart(uripart-selector, member of type URI)
    uripart-selector   := site | protocol | extension | dir[n]
    
  • All expressions must be one of the following: a date expression, a hash expression, a member value expression, or a URI expression.

  • All expressions need to specify the member name of the base class from which this dimension is derived.

  • If the expression is a date expression, the base member must be of type DateTime. Date-selector is to select the format and parts of a DateTime value that will be used as the dimension value in the aggregation class. For example, yy means that only the two-digit year part (for example, 99) of the base class DateTime member will be used as the dimension value in the aggregation class. Similarly, yyyy means that the four-digit year part (for example, 1999) will be used as the dimension value, mm means the two-digit month part, and so on.

  • If the expression is a hash expression, the base member must be a string, a GUID, or a binary. Hash-expression performs a hash on the base member's string/guid/binary value and uses the hash result as the dimension value of the aggregation class.

  • The member expression is simply a direct mapping from the base member to the dimension member of the summarization class. The base member needs to be a string that stores a valid HTTP URI.

  • Uri-expression can extract the different parts of a valid URI such as the site name, protocol (for example, HTTP or FTP), file extension (for example, .gif or .jpeg), or the nth level directory name and use it as the dimension value of the aggregation class.

For each measure in the summarization class, the measure expression must have the following syntax:

measure-expr      := measure-func(member name in the base class) |
    count(*)
measure-func      := sum | min | max

The count(*) function sums all rows of the base class that match the dimensions of the summarization class. Distinct counts can be obtained by creating a base-level summarization class that consists of dimensions with no measures.

The following is a list of import-time summarization limitations:

  • A summarization class cannot aggregate data from more than one base class.
  • Each summarization class should have at least two dimensions that uniquely track each import, SiteID and the TaskID. Otherwise, the Data Warehouse accumulates errors due to duplicate keys in the final summarization tables.
  • A summarization class can have a maximum of eight dimension members defined.
  • A summarization class has no limit to the number of measure members supported.
  • The uniqueness of each dimension as well as the number of summarization classes minimizes performance for both load time and resource utilizations.

Example

This section assumes that the reader is familiar with ADO and with OLE DB syntax, and knows how to define new classes, new members, and new relationships through the Commerce Server OLE DB provider. For more information, see Creating a New Class.

The following example defines two summarization classes, LogUsage and PageUsageUniqueGUID, and inserts them into the Data Warehouse schema, where the base class, Request, already exists. The sample also contains some utility functions that handle the necessary schema changes.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Public Const fPrimaryKey = 1
Public Const fMultiValued = 2
Public Const fHasDefaultVal = 4
Public Const fIsRequired = 8
Public Const fIsJoinKey = 16
Public Const fDontClear = 32
Public Const fGenerateColDef = 64
Public Const fIsUniqueKey = 128
Public Const fIsIdentityMember = 256

'--- Flags for clsdef
Public Const fGenerateIdentity = &H1
Public Const fGenerateTableDef = &H2
Public Const fGenerateKeyDef = &H4
Public Const fGeneratePartDef = &H8
Public Const fIsAbstract = &H10

Public Const fHasAggrExp = &H100  'member is aggregate
Public Const fIsDimension = &H1000
Public Const fIsMeasure = &H10000

Main
Sub Main()

    'Create an ADO connection object
    Dim objConn
    Set objConn = CreateObject("ADODB.Connection.2.5")
    
    'Create an ADO command object.
    Dim cmdCommand
    Set cmdCommand = CreateObject("ADODB.Command.2.5")
    
    'Create an ADO record object.
    Dim recNew
    Set recNew = CreateObject("ADODB.Record.2.5")
    
    'Open a connection (bind) to the provider.
    'Modify the values for Catalog, Database, User, and Password to 
    'match your resources.
    objConn.Open "URL=mscop://InProcConnect/Server=servername:" & _
     "Catalog=DWSchema:Database=database: Trusted_Connection=Yes:" & _
     "FastLoad=True"
    
    'Set the connection in the command object
    Set cmdCommand.ActiveConnection = objConn
    
    'Turn on "Schema Change" mode
    cmdCommand.CommandText = "SchemaMode=1"
    cmdCommand.Execute
    
   'Create the first aggregate
   'Modify the values passed to match your Catalog and SourceDef settings.
    CreateLogUsageAggregate objConn, "DWSchema", "test_Source"

   'Create the second aggregate
   'Modify the values passed to match your Catalog and SourceDef settings.
   CreatePageUsageUniqueGUIDAggregate objConn, "DWSchema", "test_Source"

    '------------------------------------------------
    '  Commit Schema
    '------------------------------------------------
    cmdCommand.CommandText = "CommitSchema"
    cmdCommand.Execute

    'Turn on "Schema Change" mode
    cmdCommand.CommandText = "SchemaMode=0"
    cmdCommand.Execute

End Sub


Sub CreateLogUsageAggregate(objConn, strCatalog, strSrcDef)

    'create aggr class
    strAggClassName = "LogUsage"
    strBaseClassName = "Request"

   'Modify the values passed below to match your Catalog and SourceDef 
   'settings.
    CreateClassDef objConn, strAggClassName, "DWSchema", "test_Source", _
      strBaseClassName, false

    '-- Dimension1 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "Date" 
    strMemDefType    = "FILETIME"
    strDefVal       = "1900-1-1 0:0:0.0"
    strAggrExp          = "datepart(yyyymmddhh, Timestamp)"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Dimension2 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "urikey" 
    strMemDefType    = "UUID"
    strDefVal       = "{00000000-0000-0000-0000-000000000000}"
    strAggrExp          = "uriKey"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Dimension3 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "IsRequest" 
    strMemDefType    = "SHORT"
    strDefVal       = "0"
    strAggrExp          = "IsRequest"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, true


    '-- Dimension4 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "Win32Status" 
    strMemDefType    = "ULONG"
    strDefVal       = "0"
    strAggrExp          = "Win32Status"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Dimension5 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "ReferrerDomainName" 
    strMemDefType    = "WSTR"
    strDefVal       = "Unknown"
    strAggrExp          = "ReferrerDomainName"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Dimension6 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "UserAgentName" 
    strMemDefType    = "WSTR"
    strDefVal       = "Unknown"
    strAggrExp          = "UserAgentName"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Dimension7 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "SiteName" 
    strMemDefType    = "WSTR"
    strDefVal       = "Unknown"
    strAggrExp          = "SiteName"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Dimension8 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "TaskID" 
    strMemDefType    = "LONG"
    strDefVal       = "0"
    strAggrExp          = "TaskID"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Measure1 : create the measure
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsMeasure
    strMemDef       = "RequestCount" 
    strMemDefType    = "LONG"
    strDefVal       = "0"
    strAggrExp          = "count(*)"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, true


    '-- Relation1 : create the relationship to a dimension class
    strClsParent   = "Date"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "DTimestamp"
    strChildMem         = "Date"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem


    '-- Relation2 : create the relationship to a dimension class
    strClsParent   = "uri"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "urikey"
    strChildMem         = "urikey"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem


    '-- Relation3 : create the relationship to a dimension class
    strClsParent   = "referrerdomain"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "ReferrerDomainName"
    strChildMem         = "ReferrerDomainName"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem


    '-- Relation4 : create the relationship to a dimension class
    strClsParent   = "useragent"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "UserAgentName"
    strChildMem         = "UserAgentName"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem


    '-- Relation5 : create the relationship to a dimension class
    strClsParent   = "win32status"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "Win32Status"
    strChildMem         = "Win32Status"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem


    '-- Relation6 : create the relationship to a dimension class
    strClsParent   = "site"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "SiteName"
    strChildMem         = "SiteName"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem


    '-- Relation7 : create the relationship to a dimension class
    strClsParent   = "taskhistory"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "TaskID"
    strChildMem         = "TaskID"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem


    '-- Creating the key definition for this aggregate, this is going to      
    '-- be consisted of all the dimension members.

    strKeyDefName = strAggClassName + "Key"
    CreateKeyDef objConn, strAggClassName, strKeyDefName

    strMemDefName = "DateID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 0
    strMemDefName = "IsRequest"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 1
    strMemDefName = "Win32StatusID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 2
    strMemDefName = "SiteID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 3
    strMemDefName = "TaskHistoryID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 4
    strMemDefName = "ReferrerDomainID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 5
    strMemDefName = "UserAgentID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 6
    strMemDefName = "uriID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 7
  
End Sub


Sub CreatePageUsageUniqueGUIDAggregate(objConn, strCatalog, strSrcDef)

    'create aggr class
    strAggClassName = "PageUsageUniqueGUID"
    strBaseClassName = "Request"

   'Modify the values passed below to match your Catalog and SourceDef settings.
    CreateClassDef objConn, strAggClassName, "DWSchema", "test_Source", _
      strBaseClassName, false

    '-- Dimension1 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "DTimestamp" 
    strMemDefType    = "FILETIME"
    strDefVal       = "1900-1-1 0:0:0.0"
    strAggrExp          = "datepart(yyyymmddhh, Timestamp)"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Dimension2 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "urikey" 
    strMemDefType    = "UUID"
    strDefVal       = "{00000000-0000-0000-0000-000000000000}"
    strAggrExp          = "uriKey"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Dimension3 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "userKey" 
    strMemDefType    = "UUID"
    strDefVal       = "{00000000-0000-0000-0000-000000000000}"
    strAggrExp          = "userKey"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Dimension4 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "SiteName" 
    strMemDefType    = "WSTR"
    strDefVal       = "Unknown"
    strAggrExp          = "SiteName"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false


    '-- Dimension5 : create dimension
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsDimension
    strMemDef       = "TaskID" 
    strMemDefType    = "LONG"
    strDefVal       = "0"
    strAggrExp          = "TaskID"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, false

    '-- Measure1 : create the measure
    lMemFlags       =  fGenerateColDef +  fHasDefaultVal + fIsMeasure
    strMemDef       = "RequestCount" 
    strMemDefType    = "ULONG"
    strDefVal       = "0"
    strAggrExp          = "count(*)"
    
    CreateMemberDef objConn, strAggClassName, strMemDef, strMemDefType , _
      lMemFlags ,  strDefVal,strAggrExp, true




    '-- Relation1 : create the relationship to a dimension class
    strClsParent   = "Date"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "DTimestamp"
    strChildMem         = "DTimestamp"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem

    '-- Relation2 : create the relationship to a dimension class
    strClsParent   = "uri"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "urikey"
    strChildMem         = "urikey"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem

    '-- Relation3 : create the relationship to a dimension class
    strClsParent   = "loguser"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "userkey"
    strChildMem         = "userkey"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem


    '-- Relation4 : create the relationship to a dimension class
    strClsParent   = "site"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "SiteName"
    strChildMem         = "SiteName"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem


    '-- Relation5 : create the relationship to a dimension class
    strClsParent   = "taskhistory"
    strRelName       = strClsParent + strAggClassName
    CreateRelDef objConn , strRelName , strClsParent , strAggClassName , _
      strClsParent + "Key" , 2

    strParentKeyMem    = "TaskID"
    strChildMem         = "TaskID"
    CreateRelMemDef objConn, strRelName, strParentKeyMem, strChildMem


    '-- Creating the key definition for this aggregate, this is going to     
    '-- be consisted of all the dimension members.

    strKeyDefName = strAggClassName + "Key"
    CreateKeyDef objConn, strAggClassName, strKeyDefName

    strMemDefName = "DateID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 0
    strMemDefName = "SiteID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 1
    strMemDefName = "TaskHistoryID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 2
    strMemDefName = "loguserID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 3
    strMemDefName = "uriID"
    CreateKeyMemberDef objConn,  strKeyDefName, strMemDefName, 4
  
End Sub



'-------------------------------------------------------------------------
'  Procedure : CreateClassDef
'  Parameters : objConn
'               strClsDef - name of classdef to be created
'               strCatalog - catalog in which we want to create
'               strSrcDef - source definition name
'               strBaseClsName - this is useful for aggregations
'                               simple classes can pass ""
'               bGenKeyDef = true - generate key definition automatically
'   Notes : The Schema change mode should have been set to true prior to 
'               calling this function
'
'-------------------------------------------------------------------------
Sub CreateClassDef(objConn, strClsDef, strCatalog, strSrcDef, strBaseClsName, bGenKeyDef)

    WScript.Echo "DBG: Class : " & strClsDef
    Dim rec
    Set rec = CreateObject("ADODB.Record.2.5")
     
    rec.Open "Class/" & strClsDef, objConn, 3, adCreateOverwrite
    rec("IsPersistent") = 1
    rec("ClassDefName") = strClsDef
    rec("SourceDefName") = strSrcDef
    rec("GeneratePartitionDef") = 1
    rec("GenerateTableDef") = 1
    If bGenKeyDef Then
       rec("GenerateKeyDef") = 1
    Else
       rec("GenerateKeyDef") = 0
       
    End If
    
    'to create an aggregate class --
    If strBaseClsName <> "" Then
       rec("BaseClassName") = strBaseClsName
    End If
    rec("GenerateIdentity") = 1
    rec("__Commit") = 1
    rec.Fields.Update
    rec.Close
  
End Sub

'-------------------------------------------------------------------------
'  Procedure  : CreateMemberDef
'  Purpose : Utility to create members
'  Parameters : objConn
'                strClsDef - name of classdef
'                strMemDef - name of member
'                strMemDefType - type of the memberdef
'                lMemFlags - MemberDef Creation flags 
'
'  Notes : User should to set the schema mode to updatable and reset
'           after the member is created.
'-------------------------------------------------------------------------
Sub CreateMemberDef(objConn, strClsDef, strMemDef, strMemDefType ,  lMemFlags ,  strDefVal,strAggrExp, isPersistent)
Dim rec 
' On Error Resume Next
    WScript.Echo "DBG: Mem : " & strMemDef
    set rec = CreateObject("ADODB.Record.2.5")
    rec.Open "Member/" & strClsDef & "/" & strMemDef, objConn, adModeReadWrite, adCreateOverwrite
    rec("MemberDefName") = strMemDef
    If (lMemFlags And fGenerateColDef) > 0 Then  'default case
        rec("GenerateColumnDef") = 1
    End If
   
    If (lMemFlags And fPrimaryKey) > 0 Then
        rec("IsPrimaryKey") = 1
    End If
    If (lMemFlags And fMultiValued) > 0 Then
        rec("IsMultiValued") = 1
    End If
    If (lMemFlags And fHasDefaultVal) > 0 Then
        rec("DefaultValueAsStr") = strDefVal
    End If
    If (lMemFlags And fIsUniqueKey) > 0 Then
        rec("IsUniqueKey") = 1
    End If
    If (lMemFlags And fIsIdentityMember) > 0 Then
        rec("IsIsIdentityMember") = 1
    End If

    If isPersistent Then
       rec("isPersistent") = 1
    Else
       rec("isPersistent") = 0
    End If

   'member aggregate - then set the aggregate expression 
   'if (lMemFlags And fHasAggrExp) > 0 then
   '      rec("ExpressionStr") = strAggrExp
   'End if

   if (lMemFlags And fIsDimension) > 0 then
      rec("IsDimension") =1
      rec("ExpressionStr") = strAggrExp
   End if
   if (lMemFlags And fIsMeasure ) > 0 then
      rec("IsMeasure") = 1
      rec("ExpressionStr") = strAggrExp
   End if
       
    rec("TypeName") = strMemDefType
    rec("__Commit") = 1
    rec.Fields.Update
 
    rec.Close
  
End Sub


'-------------------------------------------------------------------------
'  Procedure  :  CreateRelationDef
'  Purpose : create a  Relation Definitin
'  Notes :  The classes Parent and child referred to must exist. The
'           Keydefinition for the parent must exist (1-M)
'
'-------------------------------------------------------------------------
 Sub CreateRelDef(objConn , strRelName , strClsParent , strClsChild , _
        strKeyParent , iRelType )
 Dim rec 
 'On Error Resume Next
    WScript.Echo "DBG: Rel : " & strRelName
   set rec = CreateObject("ADODB.Record")
    rec.Open "Relation/" & strRelName, objConn, adModeWrite, _
        adCreateOverwrite
    rec("ParentClassName") = strClsParent
    rec("ParentClasskey") = strKeyParent
    rec("ChildClassName") = strClsChild
    rec("RelType") = iRelType
    rec("__Commit") = 1
    rec.Fields.Update

    rec.Close
    Set rec = Nothing
    
End Sub


'-------------------------------------------------------------------------
'  Procedure : CreateRelMemDef
'  Purpose : Create a Relation Member Definition : Associate key member in
'            parent with another member in child, similar to a foreign
'            key. 
'            strParentKeyMem - key of the parent 
'             strChildMem - member which is same type as parent, which
'               serves as foreign key in the child
'
'-------------------------------------------------------------------------
Sub CreateRelMemDef( objConn, strRelName, strParentKeyMem, strChildMem ) 
Dim rec
'On Error Resume Next
   set rec = CreateObject("ADODB.Record")
   rec.Open "RelMember/" & strRelName &"/" & strParentKeyMem & "/" & _
      strChildMem, objConn, adModeReadWrite, adCreateOverwrite
   rec("ChildMemName") =  strChildMem
   rec("ParentMemName") = strParentKeyMem
   rec("__Commit") = 1
   rec.Fields.Update
   rec.Close
End Sub


'-----------------------------------------------------------------------
'  Procedure : CreateKeyDef
'  Purpose : Create a key definition
'  Notes : Can create a keydefinition only if the ClassDef has been
'          created with
'           GenerateKeyDef = 0
'          Schema change mode should be enabled prior to calling this
'          function.
'------------------------------------------------------------------------
Sub CreateKeyDef( objConn, strClsDef, strKeyDefName)
Dim rec 
'On Error Resume Next
set rec = CreateObject("ADODB.Record")
   rec.Open "Key/" & strKeyDefName,objConn, adModeReadWrite, adCreateOverwrite
   rec("ClassDefName") = strClsDef
   rec("__Commit") = 1
   rec.Fields.Update
   rec.Close
End sub


'-----------------------------------------------------------------------
'  Procedure : CreateKeyMemberDef
'  Purpose : Create a key definition
'  Notes : Can create a keydefinition only if the ClassDef has been
'          created with
'           GenerateKeyDef = 0
'------------------------------------------------------------------------
Sub CreateKeyMemberDef( objConn,  strKeyDefName, strMemDefName, iOrdinalPosInKey)
Dim rec 
'On Error Resume Next
set rec = CreateObject("ADODB.Record")
   rec.Open "KeyMember/" & strKeyDefName & "/" & strMemDefName ,objConn, adModeReadWrite, adCreateOverwrite
   rec("KeyDefName")    = strKeyDefName
   rec("MemDefName") = strMemDefName
   rec("OrdinalPosInKey") = iOrdinalPosInKey
   rec("__Commit") = 1
   rec.Fields.Update
   rec.Close
End sub
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Copyright © 2005 Microsoft Corporation.
All rights reserved.