Using an access schema for accessing data in the data base
Using access schemata is a good technique for accessing data in hierarchical structures. An access schema is predefined hierarchy of properties which presents a specific view to the database. An access schema differs much from a traditional view definition, even though it fulfills similar tasks. In contrast to a view definition, an access schema is more flexible and much
easier to understand.
Access schemata are used in application programs as well as in OSI expressions. An access schema is simply defined by a hierarchy of properties. Considering the following example: In order to find out all persons that are not allowed to drive a car from the company, they are working on, the following access schema can be defined:
Person
company
cars
users
This is not the only way of defining an access schema for the problem. Usually, one may choose between many different access schemata and many different solutions. Nevertheless, this access schema visualizes, how an access schema works. The example below shows different ways of defining the access schema in an application program and in an OSI expression.
The hierarchy defined in an access schema has an important impact on the state of property handles. Thus, subordinated property handles are accessible only, when the an instance is selected in the parent property (handle). On the other hand the access schema provides automatic selection for relevant subordinated instances, i.e. selecting a person automatically provides the company collection the selected person is working for.
Of course, Access schemata are not always the best solution. In this case, the problem could simply be solved by a path expression:
Person.Where( used_cars.GetCount() == 0 ).Print;
In many cases, however, an access schema is more transparent than an operation path or a traditional view definition.
// access schema in an OSI expression
{
VARIABLES
SET<Person> &rperson = Person::Persons;
SET<Company> &rcompany = rperson.company;
SET<Car> &rcars = rcompany.cars;
SET<Person> &rusers = rcars.users;
CHAR &rpid = rperson.pid;
PROCESS
while ( rperson.next )
while ( rcompany.next )
while ( rcars.next )
if ( !rusers.get(rpid).Exist ) // when not being a car user
rperson.Print();
}
// access schema in a C++ program
Property rperson(database,"Person::Persons",Read);
Property rcompany(&rperson,"company"); // use pointer to parent
Property rcars(&rcompany,"cars"); // in order to get original property
Property rusers(&rcars,"users");
Property rpid(&rperson,"pid");
while ( rperson.next() )
while ( rcompany.next() )
while ( rcars.next() )
if ( !rusers.get(pid).Exist() )
rperson.executeExpression("Print");