protected override IVsDataReader SelectObjects(string typeName,
                                                       object[] restrictions, string[] properties, object[] parameters)
        {
            if (typeName == null)
            {
                throw new ArgumentNullException("typeName");
            }

            // Execute a SQL statement to get the property values
            SampleConnection conn = Site.GetLockedProviderObject() as SampleConnection;

            Debug.Assert(conn != null, "Invalid provider object.");
            if (conn == null)
            {
                // This should never occur
                throw new NotSupportedException();
            }
            try
            {
                // Ensure the connection is open
                if (Site.State != DataConnectionState.Open)
                {
                    Site.Open();
                }

                // Create a command object
                SampleCommand comm = (SampleCommand)conn.CreateCommand();

                // Choose and format SQL based on the type
                if (typeName.Equals(SqlObjectTypes.Root,
                                    StringComparison.OrdinalIgnoreCase))
                {
                    comm.CommandText = rootEnumerationSql;
                }
                else if (restrictions.Length == 0 ||
                         !(restrictions[0] is string))
                {
                    throw new ArgumentException(
                              "Missing required restriction(s).");
                }
                else if (typeName.Equals(SqlObjectTypes.Index,
                                         StringComparison.OrdinalIgnoreCase))
                {
                    comm.CommandText = FormatSqlString(
                        indexEnumerationSql,
                        restrictions,
                        indexEnumerationDefaults);
                }
                else if (typeName.Equals(SqlObjectTypes.IndexColumn,
                                         StringComparison.OrdinalIgnoreCase))
                {
                    comm.CommandText = FormatSqlString(
                        indexColumnEnumerationSql,
                        restrictions,
                        indexColumnEnumerationDefaults);
                }
                else if (typeName.Equals(SqlObjectTypes.ForeignKey,
                                         StringComparison.OrdinalIgnoreCase))
                {
                    comm.CommandText = FormatSqlString(
                        foreignKeyEnumerationSql,
                        restrictions,
                        foreignKeyEnumerationDefaults);
                }
                else if (typeName.Equals(SqlObjectTypes.ForeignKeyColumn,
                                         StringComparison.OrdinalIgnoreCase))
                {
                    comm.CommandText = FormatSqlString(
                        foreignKeyColumnEnumerationSql,
                        restrictions,
                        foreignKeyColumnEnumerationDefaults);
                }
                else if (typeName.Equals(SqlObjectTypes.StoredProcedure,
                                         StringComparison.OrdinalIgnoreCase))
                {
                    comm.CommandText = FormatSqlString(
                        storedProcedureEnumerationSql,
                        restrictions,
                        storedProcedureEnumerationDefaults);
                }
                else if (typeName.Equals(SqlObjectTypes.StoredProcedureParameter,
                                         StringComparison.OrdinalIgnoreCase))
                {
                    comm.CommandText = FormatSqlString(
                        storedProcedureParameterEnumerationSql,
                        restrictions,
                        storedProcedureParameterEnumerationDefaults);
                }
                else if (typeName.Equals(SqlObjectTypes.StoredProcedureColumn,
                                         StringComparison.OrdinalIgnoreCase))
                {
                    if (restrictions.Length < 3 ||
                        !(restrictions[0] is string) ||
                        !(restrictions[1] is string) ||
                        !(restrictions[2] is string))
                    {
                        throw new ArgumentException(
                                  "Missing required restriction(s).");
                    }

                    //
                    // In order to implement stored procedure columns we
                    // execute the stored procedure in schema only mode
                    // and intepret the resulting schema table.
                    //

                    // Format the command type and text
                    comm.CommandType = CommandType.StoredProcedure;
                    comm.CommandText = String.Format(
                        CultureInfo.CurrentCulture,
                        "[{0}].[{1}].[{2}]",
                        (restrictions[0] as string).Replace("]", "]]"),
                        (restrictions[1] as string).Replace("]", "]]"),
                        (restrictions[2] as string).Replace("]", "]]"));

                    // Get the schema of the stored procedure
                    DataTable    schemaTable = null;
                    DbDataReader reader      = null;
                    try
                    {
                        // SqlCommandBuilder.DeriveParameters(comm);
                        reader      = comm.ExecuteReader(CommandBehavior.SchemaOnly);
                        schemaTable = reader.GetSchemaTable();
                    }
                    catch (SqlException)
                    {
                        // The DeriveParameters and GetSchemaTable calls can
                        // be flaky; catch SqlException here because we would
                        // rather return an empty result set than an error.
                    }
                    catch (InvalidOperationException)
                    {
                        // DeriveParameters sometimes throws this as well
                    }
                    finally
                    {
                        if (reader != null)
                        {
                            reader.Close();
                        }
                    }

                    // Build a different data table to contain the right
                    // information (must have full identifier)
                    DataTable dataTable = new DataTable();
                    dataTable.Locale = CultureInfo.CurrentCulture;
                    dataTable.Columns.Add("Database", typeof(string));
                    dataTable.Columns.Add("Schema", typeof(string));
                    dataTable.Columns.Add("StoredProcedure", typeof(string));
                    dataTable.Columns.Add("Name", typeof(string));
                    dataTable.Columns.Add("Ordinal", typeof(int));
                    dataTable.Columns.Add("ProviderType", typeof(int));
                    dataTable.Columns.Add("FrameworkType", typeof(Type));
                    dataTable.Columns.Add("MaxLength", typeof(int));
                    dataTable.Columns.Add("Precision", typeof(short));
                    dataTable.Columns.Add("Scale", typeof(short));
                    dataTable.Columns.Add("IsNullable", typeof(bool));

                    // Populate the data table if a schema table was returned
                    if (schemaTable != null)
                    {
                        foreach (DataRow row in schemaTable.Rows)
                        {
                            dataTable.Rows.Add(
                                restrictions[0],
                                restrictions[1],
                                restrictions[2],
                                row["ColumnName"],
                                row["ColumnOrdinal"],
                                row["ProviderType"],
                                row["DataType"],
                                row["ColumnSize"],
                                row["NumericPrecision"],
                                row["NumericScale"],
                                row["AllowDBNull"]);
                        }
                    }

                    return(new AdoDotNetTableReader(dataTable));
                }
                else if (typeName.Equals(SqlObjectTypes.Function,
                                         StringComparison.OrdinalIgnoreCase))
                {
                    comm.CommandText = FormatSqlString(
                        functionEnumerationSql,
                        restrictions,
                        functionEnumerationDefaults);
                }
                else if (typeName.Equals(SqlObjectTypes.FunctionParameter,
                                         StringComparison.OrdinalIgnoreCase))
                {
                    comm.CommandText = FormatSqlString(
                        functionParameterEnumerationSql,
                        restrictions,
                        functionParameterEnumerationDefaults);
                }
                else if (typeName.Equals(SqlObjectTypes.FunctionColumn,
                                         StringComparison.OrdinalIgnoreCase))
                {
                    comm.CommandText = FormatSqlString(
                        functionColumnEnumerationSql,
                        restrictions,
                        functionColumnEnumerationDefaults);
                }
                else
                {
                    throw new NotSupportedException();
                }

                return(new AdoDotNetReader(comm.ExecuteReader()));
            }
            finally
            {
                Site.UnlockProviderObject();
            }
        }