internal TableInfo(Database db, string name) { if (db == null) { throw new ArgumentNullException("db"); } if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException("name"); } this.name = name; using (View columnsView = db.OpenView("SELECT * FROM `{0}`", name)) { this.columns = new ColumnCollection(columnsView); } this.primaryKeys = new ReadOnlyCollection<string>( TableInfo.GetTablePrimaryKeys(db, name)); }
internal MergeException(Database db, string conflictsTableName) : base("Merge failed.") { if (conflictsTableName != null) { IList<string> conflictTableList = new List<string>(); IList<int> conflictCountList = new List<int>(); using (View view = db.OpenView("SELECT `Table`, `NumRowMergeConflicts` FROM `" + conflictsTableName + "`")) { view.Execute(); foreach (Record rec in view) using (rec) { conflictTableList.Add(rec.GetString(1)); conflictCountList.Add((int) rec.GetInteger(2)); } } this.conflictTables = conflictTableList; this.conflictCounts = conflictCountList; } }
private static IList<string> GetTablePrimaryKeys(Database db, string table) { if (table == "_Tables") { return new string[] { "Name" }; } else if (table == "_Columns") { return new string[] { "Table", "Number" }; } else if (table == "_Storages") { return new string[] { "Name" }; } else if (table == "_Streams") { return new string[] { "Name" }; } else { int hrec; uint ret = RemotableNativeMethods.MsiDatabaseGetPrimaryKeys( (int) db.Handle, table, out hrec); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } using (Record rec = new Record((IntPtr) hrec, true, null)) { string[] keys = new string[rec.FieldCount]; for (int i = 0; i < keys.Length; i++) { keys[i] = rec.GetString(i + 1); } return keys; } } }
/// <summary> /// Merges another database with this database. /// </summary> /// <param name="otherDatabase">The database to be merged into this database</param> /// <exception cref="MergeException">merge failed due to a schema difference or data conflict</exception> /// <exception cref="InvalidHandleException">the Database handle is invalid</exception> /// <remarks><p> /// MsiDatabaseMerge does not copy over embedded cabinet files or embedded transforms from /// the reference database into the target database. Embedded data streams that are listed in /// the Binary table or Icon table are copied from the reference database to the target database. /// Storage embedded in the reference database are not copied to the target database. /// </p><p> /// The Merge method merges the data of two databases. These databases must have the same /// codepage. The merge fails if any tables or rows in the databases conflict. A conflict exists /// if the data in any row in the first database differs from the data in the corresponding row /// of the second database. Corresponding rows are in the same table of both databases and have /// the same primary key in both databases. The tables of non-conflicting databases must have /// the same number of primary keys, same number of columns, same column types, same column names, /// and the same data in rows with identical primary keys. Temporary columns however don't matter /// in the column count and corresponding tables can have a different number of temporary columns /// without creating conflict as long as the persistent columns match. /// </p><p> /// If the number, type, or name of columns in corresponding tables are different, the /// schema of the two databases are incompatible and the installer will stop processing tables /// and the merge fails. The installer checks that the two databases have the same schema before /// checking for row merge conflicts. If the schemas are incompatible, the databases have be /// modified. /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabasemerge.asp">MsiDatabaseMerge</a> /// </p></remarks> public void Merge(Database otherDatabase) { this.Merge(otherDatabase, null); }
public void Merge(Database otherDatabase, string errorTable) { if (otherDatabase == null) { throw new ArgumentNullException("otherDatabase"); } uint ret = NativeMethods.MsiDatabaseMerge((int) this.Handle, (int) otherDatabase.Handle, errorTable); if (ret != 0) { if (ret == (uint) NativeMethods.Error.FUNCTION_FAILED) { throw new MergeException(this, errorTable); } else if (ret == (uint) NativeMethods.Error.DATATYPE_MISMATCH) { throw new MergeException("Schema difference between the two databases."); } else { throw InstallerException.ExceptionFromReturnCode(ret); } } }
public void CreateTransformSummaryInfo( Database referenceDatabase, string transformFile, TransformErrors errors, TransformValidations validations) { if (referenceDatabase == null) { throw new ArgumentNullException("referenceDatabase"); } if (string.IsNullOrWhiteSpace(transformFile)) { throw new ArgumentNullException("transformFile"); } uint ret = NativeMethods.MsiCreateTransformSummaryInfo( (int) this.Handle, (int) referenceDatabase.Handle, transformFile, (int) errors, (int) validations); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
public bool GenerateTransform(Database referenceDatabase, string transformFile) { if (referenceDatabase == null) { throw new ArgumentNullException("referenceDatabase"); } if (string.IsNullOrWhiteSpace(transformFile)) { throw new ArgumentNullException("transformFile"); } uint ret = NativeMethods.MsiDatabaseGenerateTransform((int) this.Handle, (int) referenceDatabase.Handle, transformFile, 0, 0); if (ret == (uint) NativeMethods.Error.NO_DATA) { return false; } else if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return true; }
public static Session OpenPackage(Database database, bool ignoreMachineState) { if (database == null) { throw new ArgumentNullException("database"); } return Installer.OpenPackage( String.Format(CultureInfo.InvariantCulture, "#{0}", database.Handle), ignoreMachineState); }