How rules work
Rules are geodatabase objects associated with specific object classes that model business logic by defining constraints on the classes' objects or features. They do not actively restrict the behavior or values of the objects, but are accessed during validation to determine which objects are in violation of the rules, and therefore invalid. The geodatabase will not enforce the constraints defined by rules when data is created or modified, but can be used to identify the invalid data at an application's request. Rules can be defined at both the class level or at the subtype level.
The following are the types of rules that can be applied to geodatabase classes:
- Attribute rules—Can be applied to any class that is registered with the geodatabase (and contains an applicable field).
- Connectivity rules—Can be applied to geometric networks.
- Relationship rules—Can be applied to relationship classes.
From a programming perspective, all rules are subclasses of an abstract rule class and implement the IRule interface. Most of the members defined by this interface are currently reserved—the exception being the Type property—and should not be used by developers. Type is a read-only property that indicates the rule type from the esriRuleType enumeration. The concrete AttributeRule and RelationshipRule classes each have corresponding IAttributeRule and IRelationshipRule interfaces. The ConnectivityRule class is abstract, but its two subclasses—JunctionConnectivityRule and EdgeConnectivityRule—also have class-specific interfaces, IJunctionConnectivityRule[2] and IEdgeConnectivityRule. The following illustration shows an object model diagram (OMD) with the hierarchy of rule classes:
Once rules have been created, validation can be performed to ensure that a class (or specific objects in a class) conforms to the rules. For more information about validation, see Validating features.
Another type of rule (topology rule) exists in the geodatabase. Although it implements the IRule interface, it is significantly different from the other rules as it is not evaluated during calls to the IValidation interface; instead, it is evaluated during topology validation. It is also not directly associated with classes, as the other rules are, but with topologies. These differences place this type of rule outside the scope of this topic. For more information on topology rules, see Checking for topology error features in a geodatabase topology.
Attribute rules
Attribute rules are used to define attribute-specific rules on a field in a specific object class or feature class. A class can have multiple attribute rules, with a maximum of one rule per field, per subtype. Attribute rules are used to perform field-specific validation on geodatabase objects and features and make use of geodatabase domains. The creation of an attribute rule is performed by associating the domain to a field and subtype.
The following are the ways to associate a domain with a field in a geodatabase, with the side-effect being the creation of an attribute rule (the same members can be used to delete an attribute rule and remove the field-domain association):
- When creating a field, set the IFieldEdit.Domain property to an attribute domain.
- The IClassSchemaEdit.AlterDomain method can be used to assign a domain to an existing field.
- The ISubtypes.Domain property can be used to create an attribute rule at the subtype level.
Although it is possible to instantiate an attribute rule, it is not recommended. The IValidation.AddRule and IValidation.DeleteRule methods are deprecated and might cause unexpected behavior. Only create an attribute rule by using one of the previously mentioned approaches in this section.
The IAttributeRule interface defines the following properties and method:
- DomainName—Domain names associated by the rule.
- FieldName—Field names associated by the rule.
- SubtypeCode—Numeric subtype code the rule applies to (if it is not subtype specific, it has a value of 0).
- Validate—Method that validates a single row, using a single attribute rule at a time.
The primary role of attribute domains is during class-level validation, using the IValidation interface. As each row is being validated in this process, the rows' values are validated against each of the classes' applicable attribute rules. When used in this manner, developers do not need to directly invoke the attribute rules' validation functionality, but should rely on the IValidation interface to handle the process. In some cases, it can be beneficial to use an attribute rule's Validate method outside of the usual IValidation process (for example, when fine-grained validation is required for performance considerations).
An example of where attribute rule validation can be leveraged is in an ArcMap Editor event listener that actively enforces a specific rule, perhaps one that associates a range domain with a field. If a value is entered that is outside of the domain, it is automatically changed to the highest or lowest value of the domain. Rather than using the IValidation or IValidate interfaces for validation—which checks every type of rule, along with any custom validation code—performing rule-specific validation offers performance benefits. It can implement the OnChangeFeature method in a manner similar to the following code example:
[C#]
// Set the attributeRule, defaultValue, and fieldIndex values in
// a routine that only runs once, for example, a constructor. The
// defaultValue is the field's default value.
public void OnChangeFeature(IObject obj)
{
// Use the attribute rule to validate the object.
String errorMessage = null;
if (!attributeRule.Validate(obj, out errorMessage))
{
// Validation failed. Set the field value to the default value.
obj.set_Value(fieldIndex, defaultValue);
}
}
[VB.NET]
' Set the attributeRule, defaultValue, and fieldIndex values in
' a routine that only runs once, for example, a constructor. The
' defaultValue is the field's default value.
Public Sub OnChangeFeature(ByVal obj As IObject)
' Use the attribute rule to validate the object.
Dim errorMessage As String = Nothing
If Not attributeRule.Validate(obj, errorMessage) Then
' Validation failed. Set the field value to the default value.
obj.Value(fieldIndex) = defaultValue
End If
End Sub
For more information on domains, see
Creating and modifying domains and
Assigning domains to fields.
Connectivity rules
Connectivity rules can be used to define the network features (edges and junctions) that can connect to other network features. Consider a water network containing feature classes for hydrants and laterals. A hydrant should be able to connect to a hydrant lateral, but should not be connected to a water main. A connectivity rule can be used to enforce this type of rule at the class level or subtype level.
For more information on connectivity rules, see
Adding and working with connectivity rules in a geometric network.
Relationship rules
Relationship rules provide an additional degree of control over the cardinality of a relationship class. They can be used to specify "ranges" of valid cardinality in one-to-many or many-to-many relationship classes, and can be applied at a class level or subtype level. For example, in a one-to-many relationship class, an object might have two, three, or four related objects, but any less or more violates business rules and can be considered invalid.
As a real-world example, consider a relationship class between a feature class of utility poles and a feature class of transformers. The utility poles class has two subtypes, wood and steel. Business rules dictate that a wooden pole can have a maximum of two transformers, while a steel pole can have a maximum of four. The following relationship rules can be used to model this:
- One that defines the maximum cardinality between wooden poles and transformers
- One that defines the maximum cardinality between steel poles and transformers
If a class has subtypes, class-level rules cannot be applied. Instead, create a rule for each of the classes' subtypes.
Relationship rules can be applied by creating an instance of the RelationshipRule class, setting its properties using the IRelationshipRule interface, then calling IRelationshipClass.AddRelationshipRule on the relationship class. Likewise, the IRelationshipClass.DeleteRelationshipRule method can be used to remove a rule from a relationship class. The rules can be accessed from the relationship class through the IRelationshipClass.RelationshipRules property, or from the origin and destination classes via the IValidation.Rules property.
The IRelationshipRule interface defines eight properties, four relating to the origin class and four relating to the destination class. They specify the class IDs, the minimum and maximum cardinalities for both classes, and (if the classes have subtypes) the appropriate subtype codes. The following code example shows how to create two relationship rules reflecting the business rules described in the wood and steel pole scenario:
[C#]
public void CreateRelationshipRules(IRelationshipClass relationshipClass, int
poleClassId, int transformerClassId, int woodSubtype, int steelSubtype)
{
// Create a relationship rule for wooden poles and transformers.
IRelationshipRule woodPoleRule = new RelationshipRuleClass();
woodPoleRule.OriginClassID = poleClassId;
woodPoleRule.OriginSubtypeCode = woodSubtype;
woodPoleRule.DestinationClassID = transformerClassId;
woodPoleRule.DestinationMinimumCardinality = 0;
woodPoleRule.DestinationMaximumCardinality = 2;
woodPoleRule.DestinationSubtypeCode = 0;
relationshipClass.AddRelationshipRule(woodPoleRule);
// Create a relationship rule for steel poles and transformers.
IRelationshipRule steelPoleRule = new RelationshipRuleClass();
steelPoleRule.OriginClassID = poleClassId;
steelPoleRule.OriginSubtypeCode = steelSubtype;
steelPoleRule.DestinationClassID = transformerClassId;
steelPoleRule.DestinationMinimumCardinality = 0;
steelPoleRule.DestinationMaximumCardinality = 4;
steelPoleRule.DestinationSubtypeCode = 0;
relationshipClass.AddRelationshipRule(steelPoleRule);
}
[VB.NET]
Public Sub CreateRelationshipRules(ByVal relationshipClass As IRelationshipClass, ByVal poleClassId As Integer, _
ByVal transformerClassId As Integer, ByVal woodSubtype As Integer, ByVal steelSubtype As Integer)
' Create a relationship rule for wooden poles and transformers.
Dim woodPoleRule As IRelationshipRule = New RelationshipRuleClass()
woodPoleRule.OriginClassID = poleClassId
woodPoleRule.OriginSubtypeCode = woodSubtype
woodPoleRule.DestinationClassID = transformerClassId
woodPoleRule.DestinationMinimumCardinality = 0
woodPoleRule.DestinationMaximumCardinality = 2
woodPoleRule.DestinationSubtypeCode = 0
relationshipClass.AddRelationshipRule(woodPoleRule)
' Create a relationship rule for steel poles and transformers.
Dim steelPoleRule As IRelationshipRule = New RelationshipRuleClass()
steelPoleRule.OriginClassID = poleClassId
steelPoleRule.OriginSubtypeCode = steelSubtype
steelPoleRule.DestinationClassID = transformerClassId
steelPoleRule.DestinationMinimumCardinality = 0
steelPoleRule.DestinationMaximumCardinality = 4
steelPoleRule.DestinationSubtypeCode = 0
relationshipClass.AddRelationshipRule(steelPoleRule)
End Sub
The destination minimum cardinality and subtype code is set for both rules. If either minimum or maximum cardinality is defined, both must be explicitly set, as does the subtype code—even for classes without subtypes (set the value to 0). Setting just the minimum cardinality or maximum cardinality will not work. Both properties must be set together, along with the subtype code.
For more information on relationship classes
, see
Creating relationship classes.
See Also:
Validating featuresTo use the code in this topic, reference the following assemblies in your Visual Studio project. In the code files, you will need using (C#) or Imports (VB .NET) directives for the corresponding namespaces (given in parenthesis below if different from the assembly name):
Development licensing | Deployment licensing |
---|---|
ArcGIS for Desktop Basic | ArcGIS for Desktop Basic |
ArcGIS for Desktop Standard | ArcGIS for Desktop Standard |
ArcGIS for Desktop Advanced | ArcGIS for Desktop Advanced |
Engine Developer Kit | Engine |