/// <summary>
        /// Loads records for the Components table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        /// <param name="LastSequence">The sequence number of the last file in the .cab</param>
        private void LoadComponents(InstallerDatabase database, ref int LastSequence) {
            if (msi.components == null)
                return;

            Log(Level.Verbose, "Add Files:");

            using (InstallerTable
                        msiAssemblyTable = database.OpenTable("MsiAssembly"),
                        msiAssemblyNameTable = database.OpenTable("MsiAssemblyName"),
                        classTable = database.OpenTable("Class"),
                        progIdTable = database.OpenTable("ProgId"),
                        directoryTable = database.OpenTable("Directory"),
                        componentTable = database.OpenTable("Component"),
                        fileTable = database.OpenTable("File"),
                        featureComponentTable = database.OpenTable("FeatureComponents"),
                        selfRegTable = database.OpenTable("SelfReg")) {

                // Open ModuleComponents table (only exists in MSM archives)
                InstallerTable modComponentTable = null;
                if (database.VerifyTableExistance("ModuleComponents")) {
                    modComponentTable = database.OpenTable("ModuleComponents");
                }

                try {
                    foreach (MSIComponent component in msi.components) {
                        string keyFileName = component.key.file;

                        if (component.fileset == null) {
                            // Make sure the keyfile maps to a valid registry entry
                            if (((XmlElement)_xmlNode).SelectSingleNode("registry/key[@component='" + component.name + "']/value[@id='" + keyFileName + "']") == null) {
                                Log(Level.Warning, "Component '{0}' does not"
                                    + " map to a valid registry key.  Skipping...", 
                                    component.name);
                                continue;
                            }
                        }

                        if (this is MsiCreationCommand)
                            featureComponents.Add(component.name, component.feature);

                        AddModuleComponentVirtual(database, modComponentTable, component.name);

                        if (component.fileset != null) {
                            AddFiles(database, directoryTable, component,
                                fileTable,
                                component.directory, component.name, 
                                ref LastSequence, msiAssemblyTable, msiAssemblyNameTable,
                                componentTable, featureComponentTable, classTable, progIdTable, selfRegTable, modComponentTable);

                            keyFileName = GetKeyFileName(component);
                        }

                        // Insert the Component
                        componentTable.InsertRecord(component.name, component.id.ToUpper(),
                            component.directory, component.attr, component.condition, keyFileName);
                    }

                    // Add featureComponents from Task definition
                    AddFeatureComponents(featureComponentTable);
                } finally {
                    if (modComponentTable != null) {
                        modComponentTable.Close();
                    }
                }
            }
        }
        /// <summary>
        /// Adds custom table(s) to the msi database
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadUserDefinedTables(InstallerDatabase database) {
            if (msi.tables == null)
                return;

            Log(Level.Verbose, "Adding Tables:");

            foreach (MSITable table in msi.tables) {
                Log(Level.Verbose, "\t" + table.name);

                ArrayList columnList = new ArrayList();
                
                if (!database.VerifyTableExistance(table.name)) {
                    Log(Level.Verbose, "\t\tAdding table structure...");

                    string tableStructureColumns = string.Empty;
                    string tableStructureColumnTypes = string.Empty;
                    string tableStructureKeys = table.name;
                    bool firstColumn = true;

                    using (InstallerTable validationTable = database.OpenTable("_Validation")) {
                        foreach (MSITableColumn column in table.columns) { 
                            if (!firstColumn) {
                                tableStructureColumns += "\t";
                                tableStructureColumnTypes += "\t";
                            } else {
                                firstColumn = false;
                            }

                            tableStructureColumns += column.name;

                            tableStructureColumnTypes += GetMsiColumnType(column);
                            if (column.key)
                                tableStructureKeys += "\t" + column.name;

                            AddToInsertionColumnList(column, columnList);
                            AddColumnValidation(table.name, column, validationTable);
                        }
                    }
                    
                    // Create temp file.  Dump table structure contents into the file
                    // Then import the file.
                    string tableStructureContents = tableStructureColumns + "\n" + tableStructureColumnTypes + "\n" + tableStructureKeys + "\n";
                    try {
                        database.Import(tableStructureContents);
                    } catch (Exception e) {
                        throw new BuildException("Couldn't import tables", Location, e);
                    }

                    Log(Level.Verbose, "Done");
                } else {
                    foreach (MSITableColumn column in table.columns) { 
                        AddToInsertionColumnList(column, columnList);
                    }
                }

                if (table.rows != null)
                    AddTableData(database, table.name, table, columnList);
            }
        }