Active Query Builder support area

How database schema information stored in the Metadata Container?

Last modified:

Metadata Container is a tree-like structure for storing the needed information from the database schema of any modern database server. It is internally used by Active Query Builder to save metadata extracted from the database. It can be serialized to XML format and used in subsequent work sessions to reduce the database server load.

This article describes the structure and the work with Metadata Container.


Initialization of the Database Schema Tree

Active Query Builder doesn't require preliminary metadata loading.

All you need to do is to initialize the Database Schema View control by calling the QueryBuilder.InitializeDatabaseSchemaTree method in WinForms and WPF Editions or the QueryBuilder.MetadataStructure.Refresh method in the ASP.NET Edition.

This method will load the first level of the tree (list of schema or databases depending on the database server) and automatically expand the tree to the level determined by the QueryBuilder.DatabaseSchemaTreeOptions.DefaultExpandLevel property.

Deeper expansion may take more time to initialize the component depending on the size of your database schema and tree grouping mode. 

Structure of the Metadata Container

There are three types of nodes in this structure: namespaces, database objects, and sub-object items (fields and foreign keys).

  • Namespace nodes reflect object grouping according to the database schema: linked servers, databases, schemas, and packages.
  • Database objects can be tables, views, synonyms, stored procedures, or functions (only those procedures and functions that return dataset and can be used as data sources in the SELECT queries).
  • Sub-object items are fields, procedure parameters, and foreign keys.

MetadataContainer object is the root node of the structure. It stores the MetadataLoadingOptions set of properties, has the OfflineMode property, provides methods to save and load metadata to XML format and events to handle the loading of child items.

MetadataItem is the base type for all nodes of the Metadata Container. The following classes are derived from it: MetadataContainer, MetadataNamespace, MetadataObject, MetadataField, MetadataParameter, and MetadataForeignKey. The Type property determines the exact type of object for the MetadataNamespace and MetadataObject classes.

Metadata loading process

Metadata Container loads objects from the current database (according to the connection settings) by default and hides objects from other databases and linked servers. If you want to show all available databases as well as from linked servers (if any), you can set the QueryBuilder.MetadataLoadingOptions.LoadDefaultDatabaseOnly property to false.

If you want to show metadata from specific databases or linked servers only or you want to limit the schemas visible to the end-user, you can instruct the component to do this using a few simple calls described in this article.

Fine-tuning adjustment of the object's visibility can be achieved with the help of the Metadata Structure or Metadata Filters. Also, you can add the necessary objects programmatically.

For MS SQL Server, the default structure of Metadata Container can look as follows.

Metadata Container (root)
`-- Database (default)
  |-- schema1
  | `-- database objects
  `-- schema2

For MS SQL Server with the LoadDefaultDatabaseOnly property set to false, the structure can look as follows.

Metadata Container (root)
|-- Linked Server (if any)
| `-- Database(s) 
|   `-- schema(s)
|     `-- database objects
|-- Database (default)
| |-- schema1
| | `-- database objects
| `-- schema2
|   `-- database objects
`-- Database(s) 
  |-- schema1
  | `-- database objects
  `-- schema2
    `-- database objects

For MS Access that does not support any namespaces, it will look as follows.

Metadata Container (root)
`-- database objects

The algorithm of filling child nodes of Metadata Container root node is the following:

  • If the server supports linked servers:
    - trying to find linked servers;
    - adding them to the Metadata Container.
  • If the server supports multiple databases:
    - retrieving the list of databases;
    - adding them to the Metadata Container.
  • If the server doesn't support databases but supports schemas:
    - retrieving the list of schemas;
    - adding them to the Metadata Container.
  • If the server doesn't support databases and schemas:
    - retrieving the list of database objects;
    - adding them to the Metadata Container.

Metadata Container loads metadata from the database by demand. The loading starts when the user expands a node of the Database Schema Tree, when a database object is added to the query, and when the component maps objects in the parsed query to objects in the database. Learn more: Possible reasons for delays in loading metadata.

Metadata Container (as well as any other metadata item) can be forced to load all child items with the LoadAll method. It has the withFields parameter that determines whether to load fields or not as loading fields may take a long time in the case of the large database schema.

Methods and events of the Metadata Container

Each MetadataItem holds the list of child items within the Items property which of the MetadataList class. MetadataItem has the necessary methods (Find*) to find objects and to load them if they aren't loaded yet in the child items hierarchy. If you want to make searching for the loaded items only, you can get the list of loaded items of the particular type using the Items.Find*, Items.GetItems and Items.GetItemsRecursive methods. Read more about them in this article.

The ItemMetadataLoading and ItemMetadataLoaded events of the MetadataContainer allow performing pre and post-processing when child metadata items are requested to load from the database. For example, you can override the loading of fields or foreign keys for database objects or change their properties when loading is finished. You can find sample handlers of these events here.

Saving and loading the content of Metadata Container to XML

Saving the content of the Metadata Container to XML file or string allows for building queries without the necessity to be connected to the database directly. Call the LoadAll and ExportToXML methods of the MetadataContainer object to save the content of the Metadata Container in full. The LoadAll method has the "withFields" Boolean parameter which determines the necessity of database objects fields load.

queryBuilder1.MetadataContainer.LoadAll(<true or false>); // with or without fields
queryBuilder1.MetadataContainer.ExportToXML(<filename or stream>); // to file or to stream

Making a full database schema snapshot may take dozens of minutes in some cases, so we recommend displaying a progress bar and load fields for objects in the following way:

var listObjects = queryBuilder1.MetadataContainer.FindItems<MetadataObject>(MetadataType.Objects);
// initialize progress bar foreach (var mObj in listObjects) { mObj.Items.Load(MetadataType.All, false);
// increase progress }
// hide progress bar

To load metadata back from the XML file or string use the MetadataContainer.ImportFromXML method.

There's a GUI tool to edit the content of the Metadata Container. You can download it here, or you can call it from your WinForms application using the QueryBuilder.EditMetadataContainer static method.

If you have already prepared an XML file with metadata for the previous version, you can convert it into a new format using the command-line utility "XmlConverter.exe" that is shipped with the component.

Is this article helpful for you?