This class represents the information needed to establish a connection to a data source that speaks SQL (presumably a database). This class, and any that extend it, should be thread safe.
Inheritance: ConnectionDescriptor
Exemple #1
0
 /// <summary>
 /// Tests the classmapping generation off the nullable table schema.
 /// </summary>
 /// <param name="connDesc">Connection descriptor for your particular database.</param>
 /// <param name="nullableTableName">Correctly-cased name of the nullable table (some DBs
 ///                                 are case sensitive (cough oracle, postgresql cough)</param>
 public static void TestGetNullableTableMappingFromSchema(AbstractSqlConnectionDescriptor connDesc,
     string nullableTableName)
 {
     ClassMapping map = SqlConnectionUtilities.GenerateMappingFromSchema(connDesc, nullableTableName);
     Assert.AreEqual(map.TypeName, nullableTableName, "Wrong 'type' name on the generated class map.");
     Assert.AreEqual(map.Table, nullableTableName, "Wrong table name on the generated class map.");
     Assert.AreEqual(5, map.AllObjAttrsByDataCol.Count, "Wrong number of mapped fields.");
     Assert.AreEqual("ID", map.AllObjAttrsByDataCol["ID"], "Column was mapped incorrectly.");
     Assert.AreEqual("BOOLCOL", map.AllObjAttrsByDataCol["BoolCol"], "Column was mapped incorrectly.");
     Assert.AreEqual("INTCOL", map.AllObjAttrsByDataCol["IntCol"], "Column was mapped incorrectly.");
     Assert.AreEqual("FLOATCOL", map.AllObjAttrsByDataCol["FloatCol"], "Column was mapped incorrectly.");
     Assert.AreEqual("DATECOL", map.AllObjAttrsByDataCol["DateCol"], "Column was mapped incorrectly.");
 }
 /// <summary>
 /// This provides a way to query the DB and do something with the results without
 /// having to copy the "try, open, try, execute, finally, close, finally, close"
 /// type logic in a bunch of places.  This method correctly closes the objects
 /// used in the DB access in the event of an exception.
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="transaction">The transaction to do this as part of.</param>
 /// <param name="sql">The SQL statement to execute.</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <param name="invokeMe">The method to delegate to.  If null, nothing is
 ///                        done with the data reader and it is just closed.</param>
 /// <param name="parameters">The other parameters to the delegate, in whatever
 ///							 form makes sense for that delegate method.</param>
 public static void XSafeQuery(AbstractSqlConnectionDescriptor connDesc,
     SqlTransaction transaction, string sql,
     IEnumerable sqlParams, DataReaderDelegate invokeMe, Hashtable parameters)
 {
     IDbConnection conn = transaction != null
         ? transaction.Connection
         : DbCaches.Connections.Get(connDesc);
     try
     {
         IDbCommand cmd = DbCaches.Commands.Get(sql, conn);
         if (transaction != null)
         {
             cmd.Transaction = transaction.Transaction;
         }
         try
         {
             SetSQLOnCommand(connDesc, cmd, sql, sqlParams);
             IDataReader reader;
             try
             {
                 reader = cmd.ExecuteReader();
             }
             catch (Exception e)
             {
                 throw new UnableToRunSqlException(connDesc, sql, sqlParams, e);
             }
             try
             {
                 if (invokeMe != null)
                 {
                     invokeMe(parameters, reader);
                 }
             }
             catch (ExceptionWithConnectionInfo)
             {
                 // The delegate may have thrown an exception that came from another
                 // database utilities call, in which case we don't want to confuse
                 // the issue by wrapping with a different SQL command.
                 throw;
             }
             catch (Exception e)
             {
                 throw new UnableToProcessSqlResultsException(connDesc, sql, sqlParams, e);
             }
             finally
             {
                 try
                 {
                     reader.Close();
                 }
                 catch (Exception e)
                 {
                     // This exception is not rethrown because we don't want to mask any
                     // previous exception that might be being thrown out of "invokeMe".
                     _log.Warn("Caught an exception while trying to close the data reader.", e);
                 }
             }
         }
         finally
         {
             DbCaches.Commands.Return(sql, conn, cmd);
         }
     }
     finally
     {
         if (transaction == null)
         {
             DbCaches.Connections.Return(connDesc, conn);
         }
     }
 }
 /// <summary>
 /// This provides a way to query the DB and do something with the results without
 /// having to copy the "try, open, try, execute, finally, close, finally, close"
 /// type logic in a bunch of places.  This method correctly closes the objects
 /// used in the DB access in the event of an exception.
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="sql">The SQL statement to execute.</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <param name="invokeMe">The method to delegate to.  If null, nothing is
 ///                        done with the data reader and it is just closed.</param>
 /// <param name="parameters">The other parameters to the delegate, in whatever
 ///							 form makes sense for that delegate method.</param>
 public static void XSafeQuery(AbstractSqlConnectionDescriptor connDesc, string sql,
     IEnumerable sqlParams, DataReaderDelegate invokeMe, Hashtable parameters)
 {
     XSafeQuery(connDesc, null, sql, sqlParams, invokeMe, parameters);
 }
 /// <summary>
 /// Drops the specified index.
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="indexName">The name of the index to remove.</param>
 /// <returns>True if successful, false otherwise.  Any exceptions will be
 ///          logged as warnings.</returns>
 public static bool DropIndex(AbstractSqlConnectionDescriptor connDesc, string indexName)
 {
     bool retVal = false;
     try
     {
         string sql = "DROP INDEX " + indexName;
         XSafeCommand(connDesc, sql, null);
         retVal = true;
     }
     catch (Exception e)
     {
         _log.Warn("Unable to drop index '" + indexName + "'.", e);
     }
     return retVal;
 }
Exemple #5
0
 /// <summary>
 /// Instantiates the data access layer with the connection descriptor for the DB.
 /// </summary>
 /// <param name="connDesc">The connection descriptor that is being used by this FastDaoLayer.</param>
 /// <param name="supportsNumRecords">If true, methods that return numbers of records affected will be
 ///                                 returning accurate numbers.  If false, they will probably return
 ///                                 FastDAO.UNKNOWN_NUM_ROWS.</param>
 protected SqlDaDdlLayer(AbstractSqlConnectionDescriptor connDesc, bool supportsNumRecords)
     : base(connDesc, supportsNumRecords)
 {
 }
Exemple #6
0
 /// <summary>
 /// Inserts the connection into the cache IF we don't have one already (we only cache one
 /// connection per unique descriptor).
 /// 
 /// This method is thread safe.
 /// 
 /// Due to MS Access not allowing more than one connection to have the DB locked for modifying at
 /// one time, any connections to Access DBs are closed and not cached.
 /// </summary>
 public void Return(AbstractSqlConnectionDescriptor connDesc, IDbConnection conn)
 {
     bool closeConn = false;
     if (!connDesc.UsePooling())
     {
         closeConn = true;
     }
     else
     {
         lock (_cache)
         {
             if (_cache.ContainsKey(connDesc))
             {
                 // already have a connection for this connstr.  We're tolerant of this, just
                 // go ahead and close the second connection.
                 closeConn = true;
             }
             else
             {
                 _cache[connDesc] = new TimestampedData<IDbConnection>(conn);
             }
         }
     }
     if (closeConn)
     {
         // Not caching it, just close it.
         try
         {
             if (_log.IsDebugEnabled)
             {
                 _log.Debug("Closing DB connection: " + conn.ConnectionString);
             }
             conn.Close();
         }
         catch (Exception e)
         {
             // This exception is not rethrown because we don't want to mask any
             // previous exception that might be being thrown out of "invokeMe".
             _log.Warn("Caught an exception while trying to close a DB connection we just used.", e);
         }
     }
 }
 /// <summary>
 /// Helper to set up a command with sql and parameters and other misc stuff.
 /// </summary>
 private static void SetSQLOnCommand(AbstractSqlConnectionDescriptor connDesc, 
     IDbCommand cmd, string sql, IEnumerable sqlParams)
 {
     if (connDesc == null)
     {
         throw new ArgumentNullException("connDesc", "Connection descriptor cannot be null.");
     }
     if (cmd == null)
     {
         throw new ArgumentNullException("cmd", "Command cannot be null.");
     }
     try
     {
         cmd.CommandType = CommandType.Text;
         cmd.CommandText = sql;
         if (sqlParams != null)
         {
             connDesc.SetParametersOnCommand(cmd, sqlParams);
         }
     }
     catch (Exception e)
     {
         _log.Warn("Unable to set parameters on sql command, " +
                   SqlUtilities.SqlParamsToString(sql, sqlParams), e);
         throw new ApplicationException("Bad parameters for sql statement.", e);
     }
 }
 /// <summary>
 /// Similar to the "XSafeQuery" method, except this executes a
 /// query that returns a single string.
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="sql">The SQL query to execute.</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <returns>The string returned by the query.</returns>
 public static string XSafeStringQuery(AbstractSqlConnectionDescriptor connDesc, string sql,
     IEnumerable sqlParams)
 {
     return XSafeStringQuery(connDesc, null, sql, sqlParams);
 }
 /// <summary>
 /// Attempts to determine if a connection can be made using the specified connection string.
 /// </summary>
 /// <param name="connDesc">Connection descriptor to test.</param>
 /// <returns>True if a connection could be made, false otherwise
 ///          (exceptions are logged at debug level).</returns>
 public static bool TestConnection(AbstractSqlConnectionDescriptor connDesc)
 {
     bool retVal = false;
     try
     {
         IDbConnection conn = DbCaches.Connections.Get(connDesc);
         if (conn != null)
         {
             DbCaches.Connections.Return(connDesc, conn);
             retVal = true;
         }
     }
     catch (Exception e)
     {
         _log.Debug("Database connection '" + connDesc + "' failed.", e);
     }
     return retVal;
 }
 /// <summary>
 /// Queries for data and populates the specified dataset.  If you do not have a dataset
 /// already, call QueryForDataSet instead.
 /// </summary>
 /// <param name="dataTableName">The name of the DataTable to put data into in the DataSet.
 ///                         May be null if you wish to use the default given by the DataAdapter.</param>
 /// <param name="sql">The parameterized SQL query (?'s for values).</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <param name="connDesc">The database connection descriptor.  This will be
 ///                        used to get the database connection.</param>
 /// <param name="fillMe">The dataset to put data into.  Must not be null.</param>
 public static void QueryIntoDataSet(AbstractSqlConnectionDescriptor connDesc, string dataTableName, string sql,
     IEnumerable sqlParams,
     DataSet fillMe)
 {
     IDbConnection conn = DbCaches.Connections.Get(connDesc);
     try
     {
         IDbCommand cmd = DbCaches.Commands.Get(sql, conn);
         try
         {
             SetSQLOnCommand(connDesc, cmd, sql, sqlParams);
             DbDataAdapter adapter = connDesc.CreateNewAdapter(cmd);
             if (dataTableName != null)
             {
                 adapter.Fill(fillMe, dataTableName);
             }
             else
             {
                 adapter.Fill(fillMe);
             }
         }
         catch (Exception e)
         {
             throw new UnableToRunSqlException("Unable to fill dataset with query: ",
                                               connDesc, sql, sqlParams, e);
         }
         finally
         {
             DbCaches.Commands.Return(sql, conn, cmd);
         }
     }
     finally
     {
         DbCaches.Connections.Return(connDesc, conn);
     }
 }
 /// <summary>
 /// Queries for data and populates the specified dataset.  If you already have a dataset,
 /// use the QueryIntoDataSet method.
 /// </summary>
 /// <param name="dataTableName">The name of the DataTable to put data into in the DataSet.
 ///                         May be null if you wish to use the default given by the DataAdapter.</param>
 /// <param name="sql">The parameterized SQL query (?'s for values).</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <param name="connDesc">The database connection descriptor.  This will be
 ///                        used to get the database connection.</param>
 /// <returns>A DataSet full of data.  Should never return null, but
 ///			 may return an empty dataset.</returns>
 public static DataSet QueryForDataSet(AbstractSqlConnectionDescriptor connDesc, string dataTableName, string sql,
     IEnumerable sqlParams)
 {
     DataSet retVal = new DataSet();
     QueryIntoDataSet(connDesc, dataTableName, sql, sqlParams, retVal);
     return retVal;
 }
 /// <summary>
 /// Similar to DbConnection.GetSchema, except this keeps the connection
 /// handling logic here in the utility class.
 /// </summary>
 /// <param name="connDesc">Connection descriptor for the database.</param>
 /// <param name="name">The name of the type of object you want schema info on.
 ///                    For example, "Columns" to get info on the columns.</param>
 /// <param name="restrictions">A magic string array that means something to
 ///                            DbConnection.GetSchema.  Should be a string array
 ///                            of the following restrictions:
 ///                            [0] = Catalog
 ///                            [1] = Owner
 ///                            [2] = Table
 ///                            [3] = TableType
 ///                            Any/all may be null.</param>
 /// <returns>A DataTable, same as DbConnection.GetSchema.</returns>
 public static DataTable GetSchema(AbstractSqlConnectionDescriptor connDesc, string name, string[] restrictions)
 {
     DataTable retVal;
     IDbConnection conn = DbCaches.Connections.Get(connDesc);
     try
     {
         if (conn is DbConnection)
         {
             retVal = ((DbConnection) conn).GetSchema(name, restrictions);
         }
         else
         {
             throw new BadConnectionTypeException(connDesc,
                     "The IDbConnection from this connection descriptor cannot return schema info.");
         }
     }
     finally
     {
         DbCaches.Connections.Return(connDesc, conn);
     }
     return retVal;
 }
 /// <summary>
 /// Generates a simplistic classmapping (without changing any column/field names) from a
 /// table's schema.  Intended for times when you are transferring data without really using it,
 /// for example from a DB to a CSV.  Will most likely only be useful for a DictionaryDAO since
 /// there is no defined .NET class to map to.
 /// 
 /// All column names will be returned in caps.
 /// </summary>
 /// <param name="connDesc">Connection descriptor for the database.</param>
 /// <param name="tableName">Name of the table to generate a mapping for.</param>
 /// <param name="columnSorter">Since auto-generated column mappings are likely used for
 ///                            purposes such as exporting to a CSV, if you wish the columns
 ///                            to be sorted in some sort of order, you may provide an
 ///                            IComparer to do so.  May be null.</param>
 /// <returns>A class mapping, the type name will be the table name, every column will be
 ///          mapped to a "field" of the same name, and no types will be specified.</returns>
 public static ClassMapping GenerateMappingFromSchema(AbstractSqlConnectionDescriptor connDesc,
     string tableName, IComparer<ClassMapColDefinition> columnSorter)
 {
     List<ClassMapColDefinition> mapCols = new List<ClassMapColDefinition>();
     // Tolerate fully qualified table names.
     string[] tableNameParts = tableName.Split('.');
     string[] searchRestrictions = new string[4];
     // Copy the parts back starting at index 2 (2 = unadorned table name, 1 = namespace, etc).
     int destIdx = 2;
     for (int x = tableNameParts.Length - 1; x >= 0 && destIdx >= 0; x--)
     {
         searchRestrictions[destIdx--] = tableNameParts[x];
     }
     DataTable schema = GetSchema(connDesc, "Columns", searchRestrictions);
     // Now this should have just the columns that are on the table we want.
     foreach (DataRow row in schema.Rows)
     {
         // The first three columns in the data rows are the fully qualified table name.
         // Since all we need are the columns, we can ignore them.
         if (!row.IsNull(3))
         {
             string colName = row[3].ToString().ToUpper();
             mapCols.Add(new ClassMapColDefinition(colName, colName, null));
         }
     }
     if (columnSorter != null)
     {
         mapCols.Sort(columnSorter);
     }
     return new ClassMapping(tableName, tableName, mapCols, false);
 }
 /// <summary>
 /// Generates a simplistic classmapping (without changing any column/field names) from a
 /// table's schema.  Intended for times when you are transferring data without really using it,
 /// for example from a DB to a CSV.  Will most likely only be useful for a DictionaryDAO since
 /// there is no defined .NET class to map to.
 /// 
 /// All column names will be returned in caps.
 /// </summary>
 /// <param name="connDesc">Connection descriptor for the database.</param>
 /// <param name="tableName">Name of the table to generate a mapping for.</param>
 /// <returns>A class mapping, the type name will be the table name, every column will be
 ///          mapped to a "field" of the same name, and no types will be specified.</returns>
 public static ClassMapping GenerateMappingFromSchema(AbstractSqlConnectionDescriptor connDesc,
     string tableName)
 {
     return GenerateMappingFromSchema(connDesc, tableName, null);
 }
 /// <summary>
 /// Similar to the other XSafe methods, except this one returns a list of
 /// strings (for example, SELECT NAME FROM EMPLOYEES).
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="transaction">The transaction to do this as part of.</param>
 /// <param name="sql">The SQL query to execute.</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <returns>A List of strings, from the first column of the results 
 ///			(presumably there is only one column in the results).  If no results
 ///			were returned, this List will be empty.</returns>
 public static IList<string> XSafeStringListQuery(AbstractSqlConnectionDescriptor connDesc,
     SqlTransaction transaction, string sql, IEnumerable sqlParams)
 {
     Hashtable parameters = DbCaches.Hashtables.Get();
     XSafeQuery(connDesc, transaction, sql, sqlParams, ReadStringsFromQuery, parameters);
     IList<string> retVal = (IList<string>)parameters["results"];
     DbCaches.Hashtables.Return(parameters);
     return retVal;
 }
 /// <summary>
 /// Creates a non-unique index on a database table.
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="indexName">Name of the index to create.</param>
 /// <param name="tableName">What table to create the index on.</param>
 /// <param name="columnNames">The columns included in the index.</param>
 public static void CreateIndex(AbstractSqlConnectionDescriptor connDesc, string indexName, string tableName,
     IEnumerable<string> columnNames)
 {
     CreateIndex(connDesc, indexName, false, tableName, columnNames);
 }
 /// <summary>
 /// Truncates a table if supported by the DB, otherwise deletes all rows (which is
 /// effectively the same, but potentially a lot slower).
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="tableName">What table we want to blow away the contents of.</param>
 public static void TruncateTable(AbstractSqlConnectionDescriptor connDesc, string tableName)
 {
     StringBuilder sql = DbCaches.StringBuilders.Get();
     if (connDesc.SupportsTruncate())
     {
         sql.Append("TRUNCATE TABLE ");
     }
     else
     {
         sql.Append("DELETE FROM ");
     }
     sql.Append(tableName);
     XSafeCommand(connDesc, sql.ToString(), null);
     DbCaches.StringBuilders.Return(sql);
 }
 /// <summary>
 /// Similar to the "XSafeQuery" method, except this executes a
 /// query that returns a single string.
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="transaction">The transaction to do this as part of.</param>
 /// <param name="sql">The SQL query to execute.</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <returns>The string returned by the query.</returns>
 public static string XSafeStringQuery(AbstractSqlConnectionDescriptor connDesc,
     SqlTransaction transaction, string sql, IEnumerable sqlParams)
 {
     string retVal = null;
     object retObj = XSafeScalarQuery(connDesc, transaction, sql, sqlParams);
     try
     {
         // If it's null, retVal will stay null.
         if (retObj != null)
         {
             retVal = retObj.ToString();
         }
     }
     catch (Exception e)
     {
         throw new UnableToProcessSqlResultsException("Result was not ToStringable. ",
                                                      connDesc, sql, sqlParams, e);
     }
     return retVal;
 }
 /// <summary>
 /// Similar to the "XSafeQuery" method, except this executes a
 /// non-query type SQL statement.
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="sql">The SQL statement to execute.</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <returns>The number of rows affected.</returns>
 public static int XSafeCommand(AbstractSqlConnectionDescriptor connDesc, string sql,
     IEnumerable sqlParams)
 {
     return XSafeCommand(connDesc, null, sql, sqlParams);
 }
 /// <summary>
 /// Similar to the "XSafeQuery" method, except this executes a
 /// non-query type SQL statement.
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="transaction">The transaction to do this as part of.</param>
 /// <param name="sql">The SQL statement to execute.</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <returns>The number of rows affected.</returns>
 public static int XSafeCommand(AbstractSqlConnectionDescriptor connDesc,
     SqlTransaction transaction, string sql, IEnumerable sqlParams)
 {
     int retVal;
     IDbConnection conn = transaction != null
         ? transaction.Connection
         : DbCaches.Connections.Get(connDesc);
     try
     {
         IDbCommand cmd = DbCaches.Commands.Get(sql, conn);
         if (transaction != null)
         {
             cmd.Transaction = transaction.Transaction;
         }
         try
         {
             SetSQLOnCommand(connDesc, cmd, sql, sqlParams);
             try
             {
                 retVal = cmd.ExecuteNonQuery();
             }
             catch (Exception e)
             {
                 throw new UnableToRunSqlException(connDesc, sql, sqlParams, e);
             }
         }
         finally
         {
             DbCaches.Commands.Return(sql, conn, cmd);
         }
     }
     finally
     {
         if (transaction == null)
         {
             DbCaches.Connections.Return(connDesc, conn);
         }
     }
     return retVal;
 }
 /// <summary>
 /// Similar to the other XSafe methods, except this one returns a list of
 /// integers (for example, SELECT AGE FROM EMPLOYEES).
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="sql">The SQL query to execute.</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <returns>A List of integers, from the first column of the results 
 ///			(presumably there is only one column in the results).  If no results
 ///			were returned, this List will be empty.  Since integers are not nullable,
 ///         NULL VALUES WILL BE IGNORED.</returns>
 public static IList<int> XSafeIntListQuery(AbstractSqlConnectionDescriptor connDesc, string sql,
     IEnumerable sqlParams)
 {
     return XSafeIntListQuery(connDesc, null, sql, sqlParams);
 }
Exemple #22
0
        /// <summary>
        /// This returns a connection from the cache, or creates a new one if necessary. 
        /// 
        /// This method is thread safe.
        /// 
        /// This method improved one test's performance (the only one I measured) by about 20%.
        /// 
        /// Since some databases cannot have more than one connection at a time, we ask the
        /// connection descriptor whether we can actually cache the connection or not.
        /// </summary>
        public IDbConnection Get(AbstractSqlConnectionDescriptor connDesc)
        {
            IDbConnection conn = null;
            if (connDesc.UsePooling())
            {
                // If it is a pooled connection, check if we have one in our cache.
                lock (_cache)
                {
                    if (_cache.ContainsKey(connDesc))
                    {
                        TimestampedData<IDbConnection> connFromCache = _cache[connDesc];
                        // This pool only caches one connection for a connection string.
                        _cache.Remove(connDesc);

                        // Don't reuse a connection that was cached more than 5 minutes ago.  We use
                        // this cache to handle the case of thousands per second, if we're querying
                        // every 5 minutes we can take the time to create a new connection.
                        if (connFromCache.Time.Ticks < (DateTime.Now.Ticks - 3000000000))
                        {
                            try
                            {
                                connFromCache.Data.Close();
                            }
                            catch (Exception e)
                            {
                                _log.Debug("Exception while closing a connection that was probably expired anyway: " +
                                           connDesc, e);
                            }
                        }
                        else
                        {
                            conn = connFromCache.Data;
                        }
                    }
                }
            }
            // If it's a bad/broken/something connection, we want a new one also.
            if ((conn == null) || (conn.State != ConnectionState.Open))
            {
                // Make a new one and put it in the cache.
                conn = connDesc.CreateNewConnection();
                try
                {
                    conn.Open();
                    if (_log.IsDebugEnabled)
                    {
                        _log.Debug("Opened connection to: " + connDesc);
                    }
                    lock (_errorCount)
                    {
                        _errorCount[connDesc] = 0;
                    }
                }
                catch (Exception e)
                {
                    // Increment the number of consecutive failures.
                    int newCount = 1;
                    lock (_errorCount)
                    {
                        if (_errorCount.ContainsKey(connDesc))
                        {
                            newCount = _errorCount[connDesc] + 1;
                        }
                        _errorCount[connDesc] = newCount;
                    }
                    throw new UnableToConnectException(connDesc, newCount, e);
                }
            }
            return conn;
        }
 /// <summary>
 /// Similar to the "XSafeQuery" method, except this executes a
 /// query that returns a single integer (such as SELECT COUNT).
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="transaction">The transaction to do this as part of.</param>
 /// <param name="sql">The SQL query to execute.</param>
 /// <param name="sqlParams">A list of objects to use as parameters
 ///							to the SQL statement.  The list may be
 ///							null if there are no parameters.</param>
 /// <returns>The integer returned by the query.</returns>
 public static int XSafeIntQuery(AbstractSqlConnectionDescriptor connDesc,
     SqlTransaction transaction, string sql, IEnumerable sqlParams)
 {
     int retVal;
     object retObj = XSafeScalarQuery(connDesc, transaction, sql, sqlParams);
     try
     {
         if (retObj == null)
         {
             throw new NullReferenceException(
                 "The sql query should have returned an int, but returned null instead.");
         }
         retVal = Convert.ToInt32(retObj);
     }
     catch (Exception e)
     {
         throw new UnableToProcessSqlResultsException("Result was not numeric. ",
                                                      connDesc, sql, sqlParams, e);
     }
     return retVal;
 }
Exemple #24
0
 /// <summary>
 /// Instantiates the data access layer with the connection descriptor for the DB.
 /// </summary>
 /// <param name="connDesc">The connection descriptor that is being used by this FastDaoLayer.</param>
 /// <param name="supportsNumRecords">If true, methods that return numbers of records affected will be
 ///                                 returning accurate numbers.  If false, they will probably return
 ///                                 FastDAO.UNKNOWN_NUM_ROWS.</param>
 public SqlDaLayer(AbstractSqlConnectionDescriptor connDesc, bool supportsNumRecords)
     : base(connDesc, supportsNumRecords)
 {
     // We have a new _connDesc attribute, so make sure we set it here.
     _connDesc = connDesc;
 }
 /// <summary>
 /// Creates an index on a database table.
 /// </summary>
 /// <param name="connDesc">The database connection descriptor.  This is used both as
 ///                        a key for caching connections/commands as well as for
 ///                        getting the actual database connection the first time.</param>
 /// <param name="indexName">Name of the index to create.</param>
 /// <param name="isUnique">Is this a unique index?</param>
 /// <param name="tableName">What table to create the index on.</param>
 /// <param name="columnNames">The columns included in the index.</param>
 public static void CreateIndex(AbstractSqlConnectionDescriptor connDesc, string indexName, bool isUnique, string tableName,
     IEnumerable<string> columnNames)
 {
     string sql = connDesc.MakeCreateIndexCommand(indexName, isUnique, tableName, columnNames);
     XSafeCommand(connDesc, sql, null);
 }