How do you create a sybase DAAB Database at runtime with no config file

Topics: Data Access Application Block
Feb 27, 2009 at 3:20 PM
We have a sybase ado 2.0 provider and we would like to use the Database without config files and provide the provider dll name at runtime. How do you do that?
Thanks
Mar 2, 2009 at 6:32 AM
Why do you need the provider dll name to be supplied during runtime?  If I understand correctly, you already have a database class specifically for SyBase.  See these threads.. 

http://entlib.codeplex.com/Thread/View.aspx?ThreadId=28490
http://entlib.codeplex.com/Thread/View.aspx?ThreadId=32305

I'm not sure which would be applicable to you but I think either solution wouldn't satisfy your requirement regarding the dynamic provider assembly name.  (I think you only need to use reflection for this).  Anyway, let me know which one would be most likely what your code will look like so I could further understand. 


Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com
Mar 2, 2009 at 9:17 PM
Edited Mar 2, 2009 at 9:17 PM
We are using ini files so need to load the config info at runtime. The dll is not in gac. Any idea how to load it in the application?

I am getting this error
The current build operation (build key Build Key[
Microsoft.Practices.EnterpriseLibrary.Data.Database, ..]) failed:
Unable to find the requested .Net Framework Data Provider. 
It may not be installed. (Strategy type ConfiguredObjectStrategy, index 2)

Thanks
Mar 3, 2009 at 5:12 AM
Hi,

At which point you got the error? can you post your code snippet ?

You can load the assembly to the application by:

http://msdn.microsoft.com/en-us/library/system.reflection.assembly.load.aspx or
http://msdn.microsoft.com/en-us/library/system.reflection.assembly.loadfile.aspx


Valiant Dudan
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com
Mar 3, 2009 at 2:05 PM

Get error

The current build operation (build key Build Key
[Microsoft.Practices.EnterpriseLibrary.Data.Database, pts]) failed:
Unable to find the requested .Net Framework Data Provider. 
It may not be installed. (Strategy type ConfiguredObjectStrategy, index 2)

Assembly.LoadFile(@"%path%\Sybase.AdoNet2.AseClient.dll" );
DictionaryConfigurationSource source = new DictionaryConfigurationSource();
ConnectionStringsSection section = new ConnectionStringsSection();
section.ConnectionStrings.Add(
 new ConnectionStringSettings(
     "pts", sqlConnString, "Sybase.Data.AseClient" ) );
source.Add( "connectionStrings", section );
DatabaseProviderFactory factory = new DatabaseProviderFactory(source);
Database db = factory.Create( "pts" );

Get the error when we execute this line
Database db = factory.Create( "pts" );

Thanks

Mar 4, 2009 at 2:45 AM
Edited Mar 4, 2009 at 4:55 AM

Oh I see,  sorry, I thought when you said about a sybase provider, you were referring to a subclass (which you created) of the Database class.The problem here is that the DatabaseProviderFactory won't be able to create your database because DAAB will only be able to create a new database type if it has a corresponding class which subclass for ADO.NET DbProviderFactory.  Since you're using a totally different provider, you're gonna have to create your own provider factory.  Check out the entlib contribution for samples on how to do this. http://www.codeplex.com/entlibcontrib/SourceControl/PatchList.aspx. This link specifically has patches for DB2 implementation, etc.

Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com

Mar 4, 2009 at 4:24 PM
I have created an AseDatabase. Is this the correct way to use it?
    AseDatabase db = new AseDatabase( sqlConnString );


Thanks

 

Mar 5, 2009 at 3:19 AM
Hi,

Yes it is. Also you can try it this way, Database db = new AseDatabase( sqlConnString ); , its just the same. In your Implementation of AseDatabase class, do you pass a instance to the base type? 
Like this one. Although this one use a different provider that you are using. Can you post you implmentation of your class?

public class SybaseDatabase : Database
{
    public SybaseDatabase(string connectionString): base(connectionString, AdsFactory.Instance)
    { }
}

Valiant Dudan
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com

 

 

Mar 5, 2009 at 1:33 PM

I have tested all the features but these are the classes

using System;
using System.Data;
using System.Data.Common;
using System.Security.Permissions;
using System.Xml;
using Microsoft.Practices.EnterpriseLibrary.Common;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Instrumentation;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Data.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data.Instrumentation;
using Microsoft.Practices.EnterpriseLibrary.Data.Properties;
using System.Transactions;
using Sybase.Data.AseClient;

namespace EnterpriseLibrary.Data.Ase
{
    /// <summary>
    /// <para>Represents a Ase Data Server database.</para>
    /// </summary>
    /// <remarks>
    /// <para>
    /// Internally uses Ase Data Server .NET provider to connect to the database.
    /// </para> 
    /// </remarks>
    //[AsePermission(SecurityAction.Demand)]
    [DatabaseAssembler( typeof( AseDatabaseAssembler ) )]
    public class AseDatabase : Database
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="DB2Database"/> class with a connection string.
        /// </summary>
        /// <param name="connectionString">The connection string.</param>
        public AseDatabase(string connectionString)
            : base( connectionString, AseClientFactory.Instance )
        {
        }

        /// <summary>
        /// <para>Gets the parameter token used to delimit parameters for the Ase Data Server database.</para>
        /// </summary>
        /// <value>
        /// <para>The '@' symbol.</para>
        /// </value>
        protected char ParameterToken
        {
            get { return '@'; }
        }

        /// <summary>
        /// <para>Executes the <see cref="AseCommand"/> and returns a new <see cref="XmlReader"/>.</para>
        /// </summary>
        /// <remarks>
        ///  Unlike other Execute... methods that take a <see cref="DbCommand"/> instance, this method
        ///  does not set the command behavior to close the connection when you close the reader.
        ///  That means you'll need to close the connection yourself, by calling the
        ///  command.Connection.Close() method.
        ///  <para>
        ///   There is one exception to the rule above. If you're using <see cref="TransactionScope"/> to provide
        ///   implicit transactions, you should NOT close the connection on this reader when you're
        ///   done. Only close the connection if <see cref="Transaction"/>.Current is null.
        ///  </para>
        /// </remarks>
        /// <param name="command">
        /// <para>The <see cref="AseCommand"/> to execute.</para>
        /// </param>
        /// <returns>
        /// <para>An <see cref="XmlReader"/> object.</para>
        /// </returns>
        public XmlReader ExecuteXmlReader(DbCommand command)
        {
            AseCommand aseCommand = CheckIfAseCommand( command );

            ConnectionWrapper wrapper = GetOpenConnection(false);
            PrepareCommand(command, wrapper.Connection);
            return DoExecuteXmlReader(aseCommand);
        }

        /// <summary>
        /// <para>Executes the <see cref="AseCommand"/> in a transaction and returns a new <see cref="XmlReader"/>.</para>
        /// </summary>
        /// <remarks>
        ///  Unlike other Execute... methods that take a <see cref="DbCommand"/> instance, this method
        ///  does not set the command behavior to close the connection when you close the reader.
        ///  That means you'll need to close the connection yourself, by calling the
        ///  command.Connection.Close() method.
        /// </remarks>
        /// <param name="command">
        /// <para>The <see cref="AseCommand"/> to execute.</para>
        /// </param>
        /// <param name="transaction">
        /// <para>The <see cref="IDbTransaction"/> to execute the command within.</para>
        /// </param>
        /// <returns>
        /// <para>An <see cref="XmlReader"/> object.</para>
        /// </returns>
        public XmlReader ExecuteXmlReader(DbCommand command, DbTransaction transaction)
        {
            AseCommand aseCommand = CheckIfAseCommand(command);

            PrepareCommand(aseCommand, transaction);
            return DoExecuteXmlReader(aseCommand);
        }

        /// <devdoc>
        /// Execute the actual XML Reader call.
        /// </devdoc>       
        private XmlReader DoExecuteXmlReader(AseCommand aseCommand)
        {
            try
            {
                DateTime startTime = DateTime.Now;
                XmlReader reader = aseCommand.ExecuteXmlReader();
                instrumentationProvider.FireCommandExecutedEvent(startTime);
                return reader;
            }
            catch (Exception e)
            {
                instrumentationProvider.FireCommandFailedEvent(aseCommand.CommandText, ConnectionStringNoCredentials, e);
                throw;
            }
        }

        private static AseCommand CheckIfAseCommand(DbCommand command)
        {
            AseCommand aseCommand = command as AseCommand;
            if (aseCommand == null) throw new ArgumentException("The command should be a AseCommand");
            return aseCommand;
        }

        /// <devdoc>
        /// Listens for the RowUpdate event on a dataadapter to support UpdateBehavior.Continue
        /// </devdoc>
        private void OnAseRowUpdated(object sender, AseRowUpdatedEventArgs rowThatCouldNotBeWritten)
        {
            if (rowThatCouldNotBeWritten.RecordsAffected == 0)
            {
                if (rowThatCouldNotBeWritten.Errors != null)
                {
                    rowThatCouldNotBeWritten.Row.RowError = "Failed to update row";
                    rowThatCouldNotBeWritten.Status = UpdateStatus.SkipCurrentRow;
                }
            }
        }

        /// <summary>
        /// Retrieves parameter information from the stored procedure specified in the <see cref="DbCommand"/> and populates the Parameters collection of the specified <see cref="DbCommand"/> object.
        /// </summary>
        /// <param name="discoveryCommand">The <see cref="DbCommand"/> to do the discovery.</param>
        /// <remarks>The <see cref="DbCommand"/> must be a <see cref="AseCommand"/> instance.</remarks>
        protected override void DeriveParameters(DbCommand discoveryCommand)
        {
            AseCommandBuilder.DeriveParameters((AseCommand)discoveryCommand);
        }

        /// <summary>
        /// Returns the starting index for parameters in a command.
        /// </summary>
        /// <returns>The starting index for parameters in a command.</returns>
        protected override int UserParametersStartIndex()
        {
            string conns = ConnectionString.ToUpper();

            Int16 userparamstartindex = 1;
            if (conns.Contains("SERVERTYPE=UNI"))
            {
                // if UniData or UniVerse databases, this needs to be 0
                userparamstartindex = 0;
            }
            return userparamstartindex;
        }

        /// <summary>
        /// Builds a value parameter name for the current database.
        /// </summary>
        /// <param name="name">The name of the parameter.</param>
        /// <returns>A correctly formated parameter name.</returns>
        public override string BuildParameterName(string name)
        {
            //if (name[0] != this.ParameterToken)
            //{
            //    return name.Insert(0, new string(this.ParameterToken, 1));
            //}
            return name;
        }

        /// <summary>
        /// Sets the RowUpdated event for the data adapter.
        /// </summary>
        /// <param name="adapter">The <see cref="DbDataAdapter"/> to set the event.</param>
        protected override void SetUpRowUpdatedEvent(DbDataAdapter adapter)
        {
            ((AseDataAdapter)adapter).RowUpdated += new AseRowUpdatedEventHandler(OnAseRowUpdated);
        }

        /// <summary>
        /// Determines if the number of parameters in the command matches the array of parameter values.
        /// </summary>
        /// <param name="command">The <see cref="DbCommand"/> containing the parameters.</param>
        /// <param name="values">The array of parameter values.</param>
        /// <returns><see langword="true"/> if the number of parameters and values match; otherwise, <see langword="false"/>.</returns>
        protected override bool SameNumberOfParametersAndValues(DbCommand command, object[] values)
        {
            int returnParameterCount = 1;
            string conns = ConnectionString.ToUpper();

            if (conns.Contains("SERVERTYPE=UNI") && (values.Length == 1) && (command.Parameters.Count == 1))
            {
                // if UniData or UniVerse databases, set to 0 for ExecuteScalar
                returnParameterCount = 0;
            }

            int numberOfParametersToStoredProcedure = command.Parameters.Count - returnParameterCount;
            int numberOfValuesProvidedForStoredProcedure = values.Length;

            return numberOfParametersToStoredProcedure == numberOfValuesProvidedForStoredProcedure;
        }

        /// <summary>
        /// <para>Adds a new instance of a <see cref="DbParameter"/> object to the command.</para>
        /// </summary>
        /// <param name="command">The command to add the parameter.</param>
        /// <param name="name"><para>The name of the parameter.</para></param>
        /// <param name="dbType"><para>One of the <see cref="DbType"/> values.</para></param>
        /// <param name="size"><para>The maximum size of the data within the column.</para></param>
        /// <param name="direction"><para>One of the <see cref="ParameterDirection"/> values.</para></param>
        /// <param name="nullable"><para>A value indicating whether the parameter accepts <see langword="null"/> (<b>Nothing</b> in Visual Basic) values.</para></param>
        /// <param name="precision"><para>The maximum number of digits used to represent the <paramref name="value"/>.</para></param>
        /// <param name="scale"><para>The number of decimal places to which <paramref name="value"/> is resolved.</para></param>
        /// <param name="sourceColumn"><para>The name of the source column mapped to the DataSet and used for loading or returning the <paramref name="value"/>.</para></param>
        /// <param name="sourceVersion"><para>One of the <see cref="DataRowVersion"/> values.</para></param>
        /// <param name="value"><para>The value of the parameter.</para></param>      
        public virtual void AddParameter(DbCommand command, string name, AseDbType dbType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
        {
            DbParameter parameter = CreateParameter(name, dbType, size, direction, nullable, precision, scale, sourceColumn, sourceVersion, value);
            command.Parameters.Add(parameter);
        }

        /// <summary>
        /// <para>Adds a new instance of a <see cref="DbParameter"/> object to the command.</para>
        /// </summary>
        /// <param name="command">The command to add the parameter.</param>
        /// <param name="name"><para>The name of the parameter.</para></param>
        /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>       
        /// <param name="direction"><para>One of the <see cref="ParameterDirection"/> values.</para></param>               
        /// <param name="sourceColumn"><para>The name of the source column mapped to the DataSet and used for loading or returning the <paramref name="value"/>.</para></param>
        /// <param name="sourceVersion"><para>One of the <see cref="DataRowVersion"/> values.</para></param>
        /// <param name="value"><para>The value of the parameter.</para></param>   
        public void AddParameter(DbCommand command, string name, AseDbType dbType, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion, object value)
        {
            AddParameter(command, name, dbType, 0, direction, false, 0, 0, sourceColumn, sourceVersion, value);
        }

        /// <summary>
        /// Adds a new Out <see cref="DbParameter"/> object to the given <paramref name="command"/>.
        /// </summary>
        /// <param name="command">The command to add the out parameter.</param>
        /// <param name="name"><para>The name of the parameter.</para></param>
        /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>       
        /// <param name="size"><para>The maximum size of the data within the column.</para></param>       
        public void AddOutParameter(DbCommand command, string name, AseDbType dbType, int size)
        {
            ParameterDirection direction = ParameterDirection.Output;
            string conns = ConnectionString.ToUpper();
            if (conns.Contains("SERVERTYPE=UNIDATA") && direction == ParameterDirection.Output)
            {
                direction = ParameterDirection.InputOutput;
            }
            // standard set of OutParameter for DB2 and IDS and UniVerse
            AddParameter(command, name, dbType, size, direction, true, 0, 0, String.Empty, DataRowVersion.Default, DBNull.Value);
        }

        /// <summary>
        /// Adds a new In <see cref="DbParameter"/> object to the given <paramref name="command"/>.
        /// </summary>
        /// <param name="command">The command to add the in parameter.</param>
        /// <param name="name"><para>The name of the parameter.</para></param>
        /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>               
        /// <remarks>
        /// <para>This version of the method is used when you can have the same parameter object multiple times with different values.</para>
        /// </remarks>       
        public void AddInParameter(DbCommand command, string name, AseDbType dbType)
        {
            AddParameter(command, name, dbType, ParameterDirection.Input, String.Empty, DataRowVersion.Default, null);
        }

        /// <summary>
        /// Adds a new In <see cref="DbParameter"/> object to the given <paramref name="command"/>.
        /// </summary>
        /// <param name="command">The commmand to add the parameter.</param>
        /// <param name="name"><para>The name of the parameter.</para></param>
        /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>               
        /// <param name="value"><para>The value of the parameter.</para></param>     
        public void AddInParameter(DbCommand command, string name, AseDbType dbType, object value)
        {
            AddParameter(command, name, dbType, ParameterDirection.Input, String.Empty, DataRowVersion.Default, value);
        }

        /// <summary>
        /// Adds a new In <see cref="DbParameter"/> object to the given <paramref name="command"/>.
        /// </summary>
        /// <param name="command">The command to add the parameter.</param>
        /// <param name="name"><para>The name of the parameter.</para></param>
        /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>               
        /// <param name="sourceColumn"><para>The name of the source column mapped to the DataSet and used for loading or returning the value.</para></param>
        /// <param name="sourceVersion"><para>One of the <see cref="DataRowVersion"/> values.</para></param>
        public void AddInParameter(DbCommand command, string name, AseDbType dbType, string sourceColumn, DataRowVersion sourceVersion)
        {
            AddParameter(command, name, dbType, 0, ParameterDirection.Input, true, 0, 0, sourceColumn, sourceVersion, null);
        }

        /// <summary>
        /// <para>Adds a new instance of a <see cref="DbParameter"/> object.</para>
        /// </summary>
        /// <param name="name"><para>The name of the parameter.</para></param>
        /// <param name="dbType"><para>One of the <see cref="DbType"/> values.</para></param>
        /// <param name="size"><para>The maximum size of the data within the column.</para></param>
        /// <param name="direction"><para>One of the <see cref="ParameterDirection"/> values.</para></param>
        /// <param name="nullable"><para>A value indicating whether the parameter accepts <see langword="null"/> (<b>Nothing</b> in Visual Basic) values.</para></param>
        /// <param name="precision"><para>The maximum number of digits used to represent the <paramref name="value"/>.</para></param>
        /// <param name="scale"><para>The number of decimal places to which <paramref name="value"/> is resolved.</para></param>
        /// <param name="sourceColumn"><para>The name of the source column mapped to the DataSet and used for loading or returning the <paramref name="value"/>.</para></param>
        /// <param name="sourceVersion"><para>One of the <see cref="DataRowVersion"/> values.</para></param>
        /// <param name="value"><para>The value of the parameter.</para></param> 
        protected DbParameter CreateParameter(string name, AseDbType dbType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
        {
            AseParameter param = CreateParameter(name) as AseParameter;
            ConfigureParameter(param, name, dbType, size, direction, nullable, precision, scale, sourceColumn, sourceVersion, value);
            return param;
        }

        /// <summary>
        /// Configures a given <see cref="DbParameter"/>.
        /// </summary>
        /// <param name="param">The <see cref="DbParameter"/> to configure.</param>
        /// <param name="name"><para>The name of the parameter.</para></param>
        /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>
        /// <param name="size"><para>The maximum size of the data within the column.</para></param>
        /// <param name="direction"><para>One of the <see cref="ParameterDirection"/> values.</para></param>
        /// <param name="nullable"><para>A value indicating whether the parameter accepts <see langword="null"/> (<b>Nothing</b> in Visual Basic) values.</para></param>
        /// <param name="precision"><para>The maximum number of digits used to represent the <paramref name="value"/>.</para></param>
        /// <param name="scale"><para>The number of decimal places to which <paramref name="value"/> is resolved.</para></param>
        /// <param name="sourceColumn"><para>The name of the source column mapped to the DataSet and used for loading or returning the <paramref name="value"/>.</para></param>
        /// <param name="sourceVersion"><para>One of the <see cref="DataRowVersion"/> values.</para></param>
        /// <param name="value"><para>The value of the parameter.</para></param> 
        protected virtual void ConfigureParameter(AseParameter param, string name, AseDbType dbType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
        {
            param.AseDbType = dbType;
            param.Size = size;
            param.Value = (value == null) ? DBNull.Value : value;
            param.Direction = direction;
            param.IsNullable = nullable;
            param.SourceColumn = sourceColumn;
            param.SourceVersion = sourceVersion;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Data.Configuration;

namespace EnterpriseLibrary.Data.Ase
{
    /// <summary>
 /// Represents the process to build an instance of <see cref="AseDatabase"/> described by configuration information.
 /// </summary>
 public class AseDatabaseAssembler : IDatabaseAssembler
 {
  /// <summary>
  /// Builds an instance of <see cref="AseDatabase"/>, based on the provided connection string.
  /// </summary>
  /// <param name="name">The name for the new database instance.</param>
  /// <param name="connectionStringSettings">The connection string for the new database instance.</param>
  /// <param name="configurationSource">The source for any additional configuration information.</param>
  /// <returns>The new Ase Data Server database instance.</returns>
  public Database Assemble(string name, ConnectionStringSettings connectionStringSettings, IConfigurationSource configurationSource)
  {
   return new AseDatabase(connectionStringSettings.ConnectionString);
  }
 }
}

Mar 6, 2009 at 4:16 AM
The implementation seems fine. Do you still get the exception? I googled your error and some says that it should be added to the machine.config, I tried adding my provider using this: http://oakleafblog.blogspot.com/2007/03/orcas-march-ctp-on-vista-database.html as my guide.

I added this entry:
   <add name="Sybase" invariant="Advantage.Data.Provider" description=".Net Framework Data Provider for Sybase" type="Advantage.Data.Provider.AdsFactory, Advantage.Data.Provider, Version=9.10.2.0, Culture=neutral, PublicKeyToken=e33137c86a38dc06"/>

as an effect. In the providerName property of the ConnectionString in the Data Access Application Block, you can see the new provider that has been added in the machine.config.

Please give this a try and see what happens.

Valiant Dudan
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com

Mar 11, 2009 at 6:14 PM
I do not have any issues after using AseDatabase. I can instantiate a db with a connection string which is what I want. However, I did change the AseDatabase to be model after sqlDatabase instead of db2. This is the new AseDatabase implementation in case somebody see and uses the code above.


using System;
using System.Data;
using System.Data.Common;
using System.Security.Permissions;
using System.Xml;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Data.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data.Configuration.Unity;
using Microsoft.Practices.EnterpriseLibrary.Data.Properties;
using System.Transactions;
using Sybase.Data.AseClient;

namespace EnterpriseLibrary.Data.Ase
{
    /// <summary>
    /// <para>Represents an Ase Data Server database.</para>
    /// </summary>
    /// <remarks>
    /// <para>
    /// Internally uses Ase Data Server .NET provider to connect to the database.
    /// </para> 
    /// </remarks>
    //[SqlClientPermission( SecurityAction.Demand )] sybase does not have
    [DatabaseAssembler( typeof( AseDatabaseAssembler ) )]
    public class AseDatabase : Database {
        /// <summary>
  /// Initializes a new instance of the <see cref="AseDatabase"/> class with a connection string.
  /// </summary>
  /// <param name="connectionString">The connection string.</param>
        public AseDatabase( string connectionString )
            : base( connectionString, AseClientFactory.Instance ) {
        }

  /// <summary>
  /// <para>Gets the parameter token used to delimit parameters for the SQL Server database.</para>
  /// </summary>
  /// <value>
  /// <para>The '@' symbol.</para>
  /// </value>
  protected char ParameterToken
  {
   get { return '@'; }
  }

  /// <summary>
  /// <para>Executes the <see cref="AseCommand"/> and returns a new <see cref="XmlReader"/>.</para>
  /// </summary>
  /// <remarks>
  ///  Unlike other Execute... methods that take a <see cref="DbCommand"/> instance, this method
  ///  does not set the command behavior to close the connection when you close the reader.
  ///  That means you'll need to close the connection yourself, by calling the
  ///  command.Connection.Close() method.
  ///  <para>
  ///   There is one exception to the rule above. If you're using <see cref="TransactionScope"/> to provide
  ///   implicit transactions, you should NOT close the connection on this reader when you're
  ///   done. Only close the connection if <see cref="Transaction"/>.Current is null.
  ///  </para>
  /// </remarks>
  /// <param name="command">
  /// <para>The <see cref="AseCommand"/> to execute.</para>
  /// </param>
  /// <returns>
  /// <para>An <see cref="XmlReader"/> object.</para>
  /// </returns>
  public XmlReader ExecuteXmlReader(DbCommand command)
  {
   AseCommand sqlCommand = CheckIfSqlCommand(command);

   ConnectionWrapper wrapper = GetOpenConnection(false);
   PrepareCommand(command, wrapper.Connection);
   return DoExecuteXmlReader(sqlCommand);
  }

  /// <summary>
  /// <para>Executes the <see cref="AseCommand"/> in a transaction and returns a new <see cref="XmlReader"/>.</para>
  /// </summary>
  /// <remarks>
  ///  Unlike other Execute... methods that take a <see cref="DbCommand"/> instance, this method
  ///  does not set the command behavior to close the connection when you close the reader.
  ///  That means you'll need to close the connection yourself, by calling the
  ///  command.Connection.Close() method.
  /// </remarks>
  /// <param name="command">
  /// <para>The <see cref="AseCommand"/> to execute.</para>
  /// </param>
  /// <param name="transaction">
  /// <para>The <see cref="IDbTransaction"/> to execute the command within.</para>
  /// </param>
  /// <returns>
  /// <para>An <see cref="XmlReader"/> object.</para>
  /// </returns>
  public XmlReader ExecuteXmlReader(DbCommand command, DbTransaction transaction)
  {
   AseCommand sqlCommand = CheckIfSqlCommand(command);

   PrepareCommand(sqlCommand, transaction);
   return DoExecuteXmlReader(sqlCommand);
  }

  /// <devdoc>
  /// Execute the actual XML Reader call.
  /// </devdoc>       
  private XmlReader DoExecuteXmlReader(AseCommand sqlCommand)
  {
   try
   {
    DateTime startTime = DateTime.Now;
    XmlReader reader = sqlCommand.ExecuteXmlReader();
    instrumentationProvider.FireCommandExecutedEvent(startTime);
    return reader;
   }
   catch (Exception e)
   {
    instrumentationProvider.FireCommandFailedEvent(sqlCommand.CommandText, ConnectionStringNoCredentials, e);
    throw;
   }
  }

  private static AseCommand CheckIfSqlCommand(DbCommand command)
  {
   AseCommand sqlCommand = command as AseCommand;
   if (sqlCommand == null)
                throw new ArgumentException( "The command should be a AseCommand" );
   return sqlCommand;
  }

  /// <devdoc>
  /// Listens for the RowUpdate event on a dataadapter to support UpdateBehavior.Continue
  /// </devdoc>
        private void OnSqlRowUpdated( object sender, AseRowUpdatedEventArgs rowThatCouldNotBeWritten )
  {
   if (rowThatCouldNotBeWritten.RecordsAffected == 0)
   {
    if (rowThatCouldNotBeWritten.Errors != null)
    {
                    rowThatCouldNotBeWritten.Row.RowError = "Failed to update row";
     rowThatCouldNotBeWritten.Status = UpdateStatus.SkipCurrentRow;
    }
   }
  }

  /// <summary>
  /// Retrieves parameter information from the stored procedure specified in the <see cref="DbCommand"/> and populates the Parameters collection of the specified <see cref="DbCommand"/> object.
  /// </summary>
  /// <param name="discoveryCommand">The <see cref="DbCommand"/> to do the discovery.</param>
  /// <remarks>The <see cref="DbCommand"/> must be a <see cref="AseCommand"/> instance.</remarks>
  protected override void DeriveParameters(DbCommand discoveryCommand)
  {
   AseCommandBuilder.DeriveParameters((AseCommand)discoveryCommand);
  }

  /// <summary>
  /// Returns the starting index for parameters in a command.
  /// </summary>
  /// <returns>The starting index for parameters in a command.</returns>
  protected override int UserParametersStartIndex()
  {
   return 1;
  }

  /// <summary>
  /// Builds a value parameter name for the current database.
  /// </summary>
  /// <param name="name">The name of the parameter.</param>
  /// <returns>A correctly formated parameter name.</returns>
  public override string BuildParameterName(string name)
  {
   if (name[0] != this.ParameterToken)
   {
    return name.Insert(0, new string(this.ParameterToken, 1));
   }
   return name;
  }

  /// <summary>
  /// Sets the RowUpdated event for the data adapter.
  /// </summary>
  /// <param name="adapter">The <see cref="DbDataAdapter"/> to set the event.</param>
  protected override void SetUpRowUpdatedEvent(DbDataAdapter adapter)
  {
   ((AseDataAdapter)adapter).RowUpdated += OnSqlRowUpdated;
  }

  /// <summary>
  /// Determines if the number of parameters in the command matches the array of parameter values.
  /// </summary>
  /// <param name="command">The <see cref="DbCommand"/> containing the parameters.</param>
  /// <param name="values">The array of parameter values.</param>
  /// <returns><see langword="true"/> if the number of parameters and values match; otherwise, <see langword="false"/>.</returns>
  protected override bool SameNumberOfParametersAndValues(DbCommand command, object[] values)
  {
   int returnParameterCount = 1;
   int numberOfParametersToStoredProcedure = command.Parameters.Count - returnParameterCount;
   int numberOfValuesProvidedForStoredProcedure = values.Length;
   return numberOfParametersToStoredProcedure == numberOfValuesProvidedForStoredProcedure;
  }

  /// <summary>
  /// <para>Adds a new instance of a <see cref="DbParameter"/> object to the command.</para>
  /// </summary>
  /// <param name="command">The command to add the parameter.</param>
  /// <param name="name"><para>The name of the parameter.</para></param>
  /// <param name="dbType"><para>One of the <see cref="DbType"/> values.</para></param>
  /// <param name="size"><para>The maximum size of the data within the column.</para></param>
  /// <param name="direction"><para>One of the <see cref="ParameterDirection"/> values.</para></param>
  /// <param name="nullable"><para>A value indicating whether the parameter accepts <see langword="null"/> (<b>Nothing</b> in Visual Basic) values.</para></param>
  /// <param name="precision"><para>The maximum number of digits used to represent the <paramref name="value"/>.</para></param>
  /// <param name="scale"><para>The number of decimal places to which <paramref name="value"/> is resolved.</para></param>
  /// <param name="sourceColumn"><para>The name of the source column mapped to the DataSet and used for loading or returning the <paramref name="value"/>.</para></param>
  /// <param name="sourceVersion"><para>One of the <see cref="DataRowVersion"/> values.</para></param>
  /// <param name="value"><para>The value of the parameter.</para></param>      
  public virtual void AddParameter(DbCommand command, string name, AseDbType dbType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
  {
   DbParameter parameter = CreateParameter(name, dbType, size, direction, nullable, precision, scale, sourceColumn, sourceVersion, value);
   command.Parameters.Add(parameter);
  }

  /// <summary>
  /// <para>Adds a new instance of a <see cref="DbParameter"/> object to the command.</para>
  /// </summary>
  /// <param name="command">The command to add the parameter.</param>
  /// <param name="name"><para>The name of the parameter.</para></param>
  /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>       
  /// <param name="direction"><para>One of the <see cref="ParameterDirection"/> values.</para></param>               
  /// <param name="sourceColumn"><para>The name of the source column mapped to the DataSet and used for loading or returning the <paramref name="value"/>.</para></param>
  /// <param name="sourceVersion"><para>One of the <see cref="DataRowVersion"/> values.</para></param>
  /// <param name="value"><para>The value of the parameter.</para></param>   
  public void AddParameter(DbCommand command, string name, AseDbType dbType, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion, object value)
  {
   AddParameter(command, name, dbType, 0, direction, false, 0, 0, sourceColumn, sourceVersion, value);
  }

  /// <summary>
  /// Adds a new Out <see cref="DbParameter"/> object to the given <paramref name="command"/>.
  /// </summary>
  /// <param name="command">The command to add the out parameter.</param>
  /// <param name="name"><para>The name of the parameter.</para></param>
  /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>       
  /// <param name="size"><para>The maximum size of the data within the column.</para></param>       
  public void AddOutParameter(DbCommand command, string name, AseDbType dbType, int size)
  {
   AddParameter(command, name, dbType, size, ParameterDirection.Output, true, 0, 0, String.Empty, DataRowVersion.Default, DBNull.Value);
  }

  /// <summary>
  /// Adds a new In <see cref="DbParameter"/> object to the given <paramref name="command"/>.
  /// </summary>
  /// <param name="command">The command to add the in parameter.</param>
  /// <param name="name"><para>The name of the parameter.</para></param>
  /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>               
  /// <remarks>
  /// <para>This version of the method is used when you can have the same parameter object multiple times with different values.</para>
  /// </remarks>       
  public void AddInParameter(DbCommand command, string name, AseDbType dbType)
  {
   AddParameter(command, name, dbType, ParameterDirection.Input, String.Empty, DataRowVersion.Default, null);
  }

  /// <summary>
  /// Adds a new In <see cref="DbParameter"/> object to the given <paramref name="command"/>.
  /// </summary>
  /// <param name="command">The commmand to add the parameter.</param>
  /// <param name="name"><para>The name of the parameter.</para></param>
  /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>               
  /// <param name="value"><para>The value of the parameter.</para></param>     
  public void AddInParameter(DbCommand command, string name, AseDbType dbType, object value)
  {
   AddParameter(command, name, dbType, ParameterDirection.Input, String.Empty, DataRowVersion.Default, value);
  }

  /// <summary>
  /// Adds a new In <see cref="DbParameter"/> object to the given <paramref name="command"/>.
  /// </summary>
  /// <param name="command">The command to add the parameter.</param>
  /// <param name="name"><para>The name of the parameter.</para></param>
  /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>               
  /// <param name="sourceColumn"><para>The name of the source column mapped to the DataSet and used for loading or returning the value.</para></param>
  /// <param name="sourceVersion"><para>One of the <see cref="DataRowVersion"/> values.</para></param>
  public void AddInParameter(DbCommand command, string name, AseDbType dbType, string sourceColumn, DataRowVersion sourceVersion)
  {
   AddParameter(command, name, dbType, 0, ParameterDirection.Input, true, 0, 0, sourceColumn, sourceVersion, null);
  }

  /// <summary>
  /// <para>Adds a new instance of a <see cref="DbParameter"/> object.</para>
  /// </summary>
  /// <param name="name"><para>The name of the parameter.</para></param>
  /// <param name="dbType"><para>One of the <see cref="DbType"/> values.</para></param>
  /// <param name="size"><para>The maximum size of the data within the column.</para></param>
  /// <param name="direction"><para>One of the <see cref="ParameterDirection"/> values.</para></param>
  /// <param name="nullable"><para>A value indicating whether the parameter accepts <see langword="null"/> (<b>Nothing</b> in Visual Basic) values.</para></param>
  /// <param name="precision"><para>The maximum number of digits used to represent the <paramref name="value"/>.</para></param>
  /// <param name="scale"><para>The number of decimal places to which <paramref name="value"/> is resolved.</para></param>
  /// <param name="sourceColumn"><para>The name of the source column mapped to the DataSet and used for loading or returning the <paramref name="value"/>.</para></param>
  /// <param name="sourceVersion"><para>One of the <see cref="DataRowVersion"/> values.</para></param>
  /// <param name="value"><para>The value of the parameter.</para></param> 
  protected DbParameter CreateParameter(string name, AseDbType dbType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
  {
   AseParameter param = CreateParameter(name) as AseParameter;
   ConfigureParameter(param, name, dbType, size, direction, nullable, precision, scale, sourceColumn, sourceVersion, value);
   return param;
  }

  /// <summary>
  /// Configures a given <see cref="DbParameter"/>.
  /// </summary>
  /// <param name="param">The <see cref="DbParameter"/> to configure.</param>
  /// <param name="name"><para>The name of the parameter.</para></param>
  /// <param name="dbType"><para>One of the <see cref="AseDbType"/> values.</para></param>
  /// <param name="size"><para>The maximum size of the data within the column.</para></param>
  /// <param name="direction"><para>One of the <see cref="ParameterDirection"/> values.</para></param>
  /// <param name="nullable"><para>A value indicating whether the parameter accepts <see langword="null"/> (<b>Nothing</b> in Visual Basic) values.</para></param>
  /// <param name="precision"><para>The maximum number of digits used to represent the <paramref name="value"/>.</para></param>
  /// <param name="scale"><para>The number of decimal places to which <paramref name="value"/> is resolved.</para></param>
  /// <param name="sourceColumn"><para>The name of the source column mapped to the DataSet and used for loading or returning the <paramref name="value"/>.</para></param>
  /// <param name="sourceVersion"><para>One of the <see cref="DataRowVersion"/> values.</para></param>
  /// <param name="value"><para>The value of the parameter.</para></param> 
  protected virtual void ConfigureParameter(AseParameter param, string name, AseDbType dbType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
  {
   param.AseDbType = dbType;
   param.Size = size;
   param.Value = (value == null) ? DBNull.Value : value;
   param.Direction = direction;
   param.IsNullable = nullable;
   param.SourceColumn = sourceColumn;
   param.SourceVersion = sourceVersion;
  }
    }       
}