// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
namespace WixToolset.Dtf.WindowsInstaller.Linq
{
using System;
using System.IO;
using WixToolset.Dtf.WindowsInstaller.Linq.Entities;
///
/// Allows any Database instance to be converted into a queryable database.
///
public static class Queryable
{
///
/// Converts any Database instance into a queryable database.
///
///
/// Queryable database instance that operates on the same
/// MSI handle.
///
/// This extension method is meant for convenient on-the-fly conversion.
/// If the existing database instance already happens to be a QDatabase,
/// then it is returned unchanged. Otherwise since the new database
/// carries the same MSI handle, only one of the instances needs to be
/// closed, not both.
///
public static QDatabase AsQueryable(this Database db)
{
QDatabase qdb = db as QDatabase;
if (qdb == null && db != null)
{
qdb = new QDatabase(db.Handle, true, db.FilePath, db.OpenMode);
}
return qdb;
}
}
///
/// Queryable MSI database - extends the base Database class with
/// LINQ query functionality along with predefined entity types
/// for common tables.
///
public class QDatabase : Database
{
///
/// Opens an existing database in read-only mode.
///
/// Path to the database file.
/// the database could not be created/opened
///
/// Because this constructor initiates database access, it cannot be used with a
/// running installation.
/// The Database object should be d after use.
/// The finalizer will close the handle if it is still open, however due to the nondeterministic
/// nature of finalization it is best that the handle be closed manually as soon as it is no
/// longer needed, as leaving lots of unused handles open can degrade performance.
///
public QDatabase(string filePath)
: base(filePath)
{
}
///
/// Opens an existing database with another database as output.
///
/// Path to the database to be read.
/// Open mode for the database
/// Database object representing the created or opened database
/// the database could not be created/opened
///
/// When a database is opened as the output of another database, the summary information stream
/// of the output database is actually a read-only mirror of the original database and thus cannot
/// be changed. Additionally, it is not persisted with the database. To create or modify the
/// summary information for the output database it must be closed and re-opened.
/// The returned Database object should be d after use.
/// The finalizer will close the handle if it is still open, however due to the nondeterministic
/// nature of finalization it is best that the handle be closed manually as soon as it is no
/// longer needed, as leaving lots of unused handles open can degrade performance.
///
public QDatabase(string filePath, string outputPath)
: base(filePath, outputPath)
{
}
///
/// Opens an existing database or creates a new one.
///
/// Path to the database file. If an empty string
/// is supplied, a temporary database is created that is not persisted.
/// Open mode for the database
/// the database could not be created/opened
///
/// To make and save changes to a database first open the database in transaction,
/// create or, or direct mode. After making the changes, always call the Commit method
/// before closing the database handle. The Commit method flushes all buffers.
/// Always call the Commit method on a database that has been opened in direct
/// mode before closing the database. Failure to do this may corrupt the database.
/// Because this constructor initiates database access, it cannot be used with a
/// running installation.
/// The Database object should be d after use.
/// The finalizer will close the handle if it is still open, however due to the nondeterministic
/// nature of finalization it is best that the handle be closed manually as soon as it is no
/// longer needed, as leaving lots of unused handles open can degrade performance.
///
public QDatabase(string filePath, DatabaseOpenMode mode)
: base(filePath, mode)
{
}
///
/// Creates a new database from an MSI handle.
///
/// Native MSI database handle.
/// True if the handle should be closed
/// when the database object is disposed
/// Path of the database file, if known
/// Mode the handle was originally opened in
protected internal QDatabase(
IntPtr handle, bool ownsHandle, string filePath, DatabaseOpenMode openMode)
: base(handle, ownsHandle, filePath, openMode)
{
}
///
/// Gets or sets a log where all MSI SQL queries are written.
///
///
/// The log can be useful for debugging, or simply to watch the LINQ magic in action.
///
public TextWriter Log { get; set; }
///
/// Gets a queryable table from the datbaase.
///
/// name of the table
public QTable this[string table]
{
get
{
return new QTable(this, table);
}
}
#if !CODE_ANALYSIS
#region Queryable tables
/// Queryable standard table with predefined specialized record type.
public QTable Components
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable CreateFolders
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable CustomActions
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable Directories
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable DuplicateFiles
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable Features
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable FeatureComponents
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable Files
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable FileHashes
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable InstallExecuteSequences
{ get { return new QTable(this, "InstallExecuteSequence"); } }
/// Queryable standard table with predefined specialized record type.
public QTable InstallUISequences
{ get { return new QTable(this, "InstallUISequence"); } }
/// Queryable standard table with predefined specialized record type.
public QTable LaunchConditions
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable Medias
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable Properties
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable Registries
{ get { return new QTable(this); } }
/// Queryable standard table with predefined specialized record type.
public QTable RemoveFiles
{ get { return new QTable(this); } }
#endregion // Queryable tables
#endif // !CODE_ANALYSIS
}
}