using System; using System.ComponentModel; using System.Data.Common; using System.Data.Jet.JetStoreSchemaDefinition; using System.Data.OleDb; using System.Reflection; using System.Transactions; namespace System.Data.Jet { public class JetConnection : DbConnection, IDisposable, ICloneable { internal DbConnection WrappedConnection { get; private set; } /// /// Initializes a new instance of the class. /// public JetConnection() { WrappedConnection = new OleDbConnection(); WrappedConnection.StateChange += WrappedConnection_StateChange; } /// /// Initializes a new instance of the class. /// /// The underling OleDb connection. public JetConnection(OleDbConnection connection) { WrappedConnection = connection; WrappedConnection.StateChange += WrappedConnection_StateChange; } /// /// Initializes a new instance of the class. /// /// The connection string. public JetConnection(string connectionString) : this() { this.ConnectionString = connectionString; } /// /// Gets or sets a value indicating whether this instance is empty. /// It is similar to connection to master and can be used only to create and drop databases /// /// /// true if this instance is empty; otherwise, false. /// public bool IsEmpty { get; set; } /// /// Gets the for this . /// protected override DbProviderFactory DbProviderFactory { get { return JetProviderFactory.Instance; } } /// /// Starts a database transaction. /// /// Specifies the isolation level for the transaction. /// /// An object representing the new transaction. /// protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) { switch (isolationLevel) { case IsolationLevel.Serializable: return new JetTransaction(WrappedConnection.BeginTransaction(IsolationLevel.ReadCommitted), this); case IsolationLevel.Chaos: case IsolationLevel.ReadCommitted: case IsolationLevel.ReadUncommitted: case IsolationLevel.RepeatableRead: case IsolationLevel.Snapshot: case IsolationLevel.Unspecified: default: return new JetTransaction(WrappedConnection.BeginTransaction(isolationLevel), this); } } /// /// Changes the current database for an open connection. /// /// Specifies the name of the database for the connection to use. public override void ChangeDatabase(string databaseName) { this.WrappedConnection.ChangeDatabase(databaseName); } /// /// Closes the connection to the database. This is the preferred method of closing any open connection. /// public override void Close() { this.WrappedConnection.Close(); } /// /// Gets or sets the string used to open the connection. /// public override string ConnectionString { get { return this.WrappedConnection.ConnectionString; } set { this.WrappedConnection.ConnectionString = value; } } /// /// Gets the time to wait while establishing a connection before terminating the attempt and generating an error. /// public override int ConnectionTimeout { get { return this.WrappedConnection.ConnectionTimeout; } } /// /// Creates and returns a object associated with the current connection. /// /// /// A object. /// protected override DbCommand CreateDbCommand() { DbCommand command = JetProviderFactory.Instance.CreateCommand(); command.Connection = this; return command; } /// /// Gets the name of the current database after a connection is opened, or the database name specified in the connection string before the connection is opened. /// public override string Database { get { return this.WrappedConnection.Database; } } /// /// Gets the name of the database server to which to connect. /// public override string DataSource { get { return this.WrappedConnection.DataSource; } } /// /// Releases the unmanaged resources used by the and optionally releases the managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { if (disposing) this.WrappedConnection.Dispose(); base.Dispose(disposing); OnDisposed(EventArgs.Empty); } /// /// Enlists in the specified transaction. /// /// A reference to an existing in which to enlist. public override void EnlistTransaction(Transaction transaction) { this.WrappedConnection.EnlistTransaction(transaction); } /// /// Returns schema information for the data source of this using the specified string for the schema name. /// /// Specifies the name of the schema to return. /// /// A that contains schema information. /// /// /// /// public override DataTable GetSchema(string collectionName) { return this.WrappedConnection.GetSchema(collectionName); } /// /// Returns schema information for the data source of this . /// /// /// A that contains schema information. /// /// /// /// public override DataTable GetSchema() { return this.WrappedConnection.GetSchema(); } /// /// Returns schema information for the data source of this using the specified string for the schema name and the specified string array for the restriction values. /// /// Specifies the name of the schema to return. /// Specifies a set of restriction values for the requested schema. /// /// A that contains schema information. /// /// /// /// public override DataTable GetSchema(string collectionName, string[] restrictionValues) { return this.WrappedConnection.GetSchema(collectionName, restrictionValues); } /// /// Opens a database connection with the settings specified by the . /// public override void Open() { if (IsEmpty) return; this.WrappedConnection.Open(); } /// /// Gets a string that represents the version of the server to which the object is connected. /// public override string ServerVersion { get { return this.WrappedConnection.ServerVersion; } } /// /// Gets or sets the of the . /// public override ISite Site { get { return this.WrappedConnection.Site; } set { this.WrappedConnection.Site = value; } } /// /// Gets a string that describes the state of the connection. /// public override ConnectionState State { get { return this.WrappedConnection.State; } } void WrappedConnection_StateChange(object sender, StateChangeEventArgs e) { OnStateChange(e); } public bool TableExists(string tableName) { ConnectionState oldConnectionState = State; bool tableExists; if (oldConnectionState == ConnectionState.Closed) Open(); try { string sqlFormat = "select count(*) from [{0}] where 1=2"; CreateCommand(String.Format(sqlFormat, tableName)).ExecuteNonQuery(); tableExists = true; } catch { tableExists = false; } if (oldConnectionState == ConnectionState.Closed) Close(); return tableExists; } public DbCommand CreateCommand(string commandText, int? commandTimeout = null) { if (String.IsNullOrEmpty(commandText)) // SqlCommand will complain if the command text is empty commandText = Environment.NewLine; var command = new JetCommand(commandText, this); if (commandTimeout.HasValue) command.CommandTimeout = commandTimeout.Value; return command; } /// /// Occurs when the component is disposed by a call to the method. /// public new event EventHandler Disposed; /// /// Raises the event. /// /// The instance containing the event data. protected virtual void OnDisposed(EventArgs e) { if (Disposed != null) Disposed(this, e); } /// /// Creates a new object that is a copy of the current instance. /// /// /// A new object that is a copy of this instance. /// object ICloneable.Clone() { JetConnection clone = new JetConnection(); clone.WrappedConnection = (DbConnection)((ICloneable)this.WrappedConnection).Clone(); return clone; } /// /// Performs an explicit conversion from to . /// /// The connection. /// /// The result of the conversion. /// public static explicit operator OleDbConnection(JetConnection connection) { return (OleDbConnection)connection.WrappedConnection; } /// /// Clears the pool. /// /// The connection. public static void ClearPool(JetConnection connection) { // Actually Jet does not support pools } /// /// Clears all pools. /// public static void ClearAllPools() { // Actually Jet does not support pools } public void CreateEmptyDatabase() { AdoxWrapper.CreateEmptyDatabase(WrappedConnection.ConnectionString); } public static string GetConnectionString(string fileName) { return $"Provider={JetConfiguration.OleDbDefaultProvider};Data Source={fileName}"; } public void DropDatabase(bool throwOnError = true) { DropDatabase(WrappedConnection.ConnectionString, throwOnError); } public static void DropDatabase(string connectionString, bool throwOnError = true) { string fileName = JetStoreDatabaseHandling.ExtractFileNameFromConnectionString(connectionString); if (string.IsNullOrWhiteSpace(fileName)) throw new Exception("Cannot retrieve file name from connection string"); JetStoreDatabaseHandling.DeleteFile(fileName.Trim(), throwOnError); } public bool DatabaseExists() { return DatabaseExists(WrappedConnection.ConnectionString); } public static bool DatabaseExists(string connectionString) { string fileName = JetStoreDatabaseHandling.ExtractFileNameFromConnectionString(connectionString); if (string.IsNullOrWhiteSpace(fileName)) throw new Exception("Cannot retrieve file name from connection string"); return System.IO.File.Exists(fileName); } } }