Back to contents pageHow to handle schema change events

How to handle schema change events

Summary

This article shows you how to handle schema change events correctly. The example application contains a simple list of object names from the UName.Naming schema. You should use this as an example of how to guarantee that your application displays the correct state of any Ubisense schema.

The example also contains a list of the 10 most recent events that occur on the UName.Naming schema and the ObjectName relation. You can use this to aid your understanding of when events occur.





Prerequisites

None. You can use this article on its own.



Example material

Save this link to get a zip file of the example material


Guide

There are 3 types of events associated with every Ubisense schema class, for example the UName.Naming.Schema. These are as follows:

There are 3 types of events associated with every Ubisense relation class. That is, every table such as ObjectName. These are as follows: If your application displays a list with some schema state in, for example the list of object names, the minimum requirements to ensure your list is up-to-date are as follows:
  1. You handle either commit events of the schema OR you handle all insert, update and delete events of the relation.
  2. You must always handle establish events.
  3. You must populate your list when your program starts. Since connecting to a schema guarantees an establish event, it is recommended that you connect after registering the event handlers to do this cleanly.

Handling schema events

You register schema event handlers by calling the appropriate members of your schema object:


        // The example schema. Here we are using the UName.Naming schema,
        // but this example applies to all Ubisense schemas.
        Ubisense.UName.Naming.Schema schema = new Ubisense.UName.Naming.Schema(false);

        // Register the event handler delegates.
        schema.AddCommitHandler(CommitHandler);
        schema.AddEstablishHandler(EstablishHandler);
        schema.AddInvalidHandler(InvalidHandler);

        // Connect as a client to the naming schema. This guarantees that
        // an establish event will occur, so should be done *after* adding
        // the establish event handler.
        schema.ConnectAsClient();



The most straightforward approach is then to fully re-populate your list from the schema cache in both the commit and establish event handlers:


        // This will be called whenever a commit event occurs.
        private void CommitHandler()
        {
            populateTable();
        }

        // This will be called whenever an establish event occurs.
        private void EstablishHandler()
        {
            populateTable();
        }

        // This will be called whenever an invalid event occurs.
        private void InvalidHandler()
        {
            // You can save the invalid state of the schema here.
            // This is provided so you can evaluate the differences
            // between the invalid state and the established state
            // and deal only with those differences.
        }



The populateTable() method for the object names example is as follows. Note in particular that the event handlers are not run on the main thread, so BeginInvoke is required if any Windows Forms components are being updated:


    // Called from schema event handler delegates, so not from the main thread.
    private void populateTable()
    {
        BeginInvoke(new MethodInvoker(delegate()
        {
            objectNameListView.Items.Clear();
            using (Ubisense.UName.Naming.ReadTransaction xact = schema.ReadTransaction())
            {
                foreach (Ubisense.UName.Naming.ObjectName.RowType row in
                         Ubisense.UName.Naming.ObjectName.name_(xact))
                {
                    objectNameListView.Items.Add(row.name_);
                }
            }
        }));
    }



Handling relation events

You register relation event handlers by calling the appropriate static members of the relation class:


        // Register the event handler delegates.
        Ubisense.UName.Naming.ObjectName.AddInsertHandler(schema, InsertHandler);
        Ubisense.UName.Naming.ObjectName.AddUpdateHandler(schema, UpdateHandler);
        Ubisense.UName.Naming.ObjectName.AddDeleteHandler(schema, DeleteHandler);



You now have much finer control because the relation event handlers have arguments specifying the old and new rows in the table:


        // Insert handler for the ObjectName relation.
        private void InsertHandler(Ubisense.UName.Naming.ObjectName.RowType row)
        {
        }

        // Update handler for the ObjectName relation.
        private void UpdateHandler(Ubisense.UName.Naming.ObjectName.RowType old,
                                   Ubisense.UName.Naming.ObjectName.RowType row)
        {
        }

        // Delete handler for the ObjectName relation.
        private void DeleteHandler(Ubisense.UName.Naming.ObjectName.RowType old)
        {
        }



Summary

This is another example application that is not really useful as an application - it is intended that you review the source code carefully and use it as a reference for writing your own code. The relevant code in the example material is found in MainForm.cs.





Back to top