示例#1
0
        private void EnsureSchemaTable()
        {
            if (_currentSchemaTable != null || FieldCount == 0)
            {
                return;
            }

            var formats = CurrentResultSet?.Formats;

            if (formats == null)
            {
                return;
            }

            var table   = new DataTable("SchemaTable");
            var columns = table.Columns;

            var columnName       = columns.Add(SchemaTableColumn.ColumnName, typeof(string));
            var columnOrdinal    = columns.Add(SchemaTableColumn.ColumnOrdinal, typeof(int));
            var columnSize       = columns.Add(SchemaTableColumn.ColumnSize, typeof(int));
            var numericPrecision = columns.Add(SchemaTableColumn.NumericPrecision, typeof(int));
            var numericScale     = columns.Add(SchemaTableColumn.NumericScale, typeof(int));
            var isUnique         = columns.Add(SchemaTableColumn.IsUnique, typeof(bool));
            var isKey            = columns.Add(SchemaTableColumn.IsKey, typeof(bool));
            var baseServerName   = columns.Add(SchemaTableOptionalColumn.BaseServerName, typeof(string));
            var baseCatalogName  = columns.Add(SchemaTableOptionalColumn.BaseCatalogName, typeof(string));
            var baseColumnName   = columns.Add(SchemaTableColumn.BaseColumnName, typeof(string));
            var baseSchemaName   = columns.Add(SchemaTableColumn.BaseSchemaName, typeof(string));
            var baseTableName    = columns.Add(SchemaTableColumn.BaseTableName, typeof(string));
            var dataType         = columns.Add(SchemaTableColumn.DataType, typeof(Type));
            var allowDBNull      = columns.Add(SchemaTableColumn.AllowDBNull, typeof(bool));
            var providerType     = columns.Add(SchemaTableColumn.ProviderType, typeof(int));
            var isAliased        = columns.Add(SchemaTableColumn.IsAliased, typeof(bool));
            var isExpression     = columns.Add(SchemaTableColumn.IsExpression, typeof(bool));
            var isIdentity       = columns.Add("IsIdentity", typeof(bool));
            var isAutoIncrement  = columns.Add(SchemaTableOptionalColumn.IsAutoIncrement, typeof(bool));
            var isRowVersion     = columns.Add(SchemaTableOptionalColumn.IsRowVersion, typeof(bool));
            var isHidden         = columns.Add(SchemaTableOptionalColumn.IsHidden, typeof(bool));
            var isLong           = columns.Add(SchemaTableColumn.IsLong, typeof(bool));
            var isReadOnly       = columns.Add(SchemaTableOptionalColumn.IsReadOnly, typeof(bool));

            columns.Add(SchemaTableOptionalColumn.ProviderSpecificDataType, typeof(Type));
            var dataTypeName = columns.Add("DataTypeName", typeof(string));

            //do we need these?
            columns.Add("XmlSchemaCollectionDatabase", typeof(string));
            columns.Add("XmlSchemaCollectionOwningSchema", typeof(string));
            columns.Add("XmlSchemaCollectionName", typeof(string));
            columns.Add("UdtAssemblyQualifiedName");
            columns.Add(SchemaTableColumn.NonVersionedProviderType, typeof(int));
            //means "is column [a sparse] set", not "is column set [to a value]"
            columns.Add("IsColumnSet", typeof(bool));

            string baseCatalogNameValue = null;
            string baseSchemaNameValue  = null;
            string baseTableNameValue   = null;

            for (var i = 0; i < formats.Length; i++)
            {
                var column    = formats[i];
                var row       = table.NewRow();
                var aseDbType = TypeMap.GetAseDbType(column);

                row[columnName]       = column.DisplayColumnName;
                row[columnOrdinal]    = i;
                row[columnSize]       = column.Length ?? -1;
                row[numericPrecision] = column.Precision ?? -1;
                row[numericScale]     = column.Scale ?? -1;
                row[isUnique]         = false; // This gets set below.
                row[isKey]            = false; // This gets set below - no idea why TDS_ROW_KEY is never set.
                row[baseServerName]   = string.Empty;
                row[baseCatalogName]  = column.CatalogName;
                row[baseColumnName]   = column.ColumnName;
                row[baseSchemaName]   = column.SchemaName;
                row[baseTableName]    = column.TableName;
                row[dataType]         = TypeMap.GetNetType(column);
                row[allowDBNull]      = column.RowStatus.HasFlag(RowFormatItemStatus.TDS_ROW_NULLALLOWED);
                row[providerType]     = aseDbType;
                row[isAliased]        = !string.IsNullOrWhiteSpace(column.ColumnLabel);
                row[isExpression]     = false; // It doesn't seem to matter that this isn't supported. The column gets flagged as TDS_ROW_UPDATABLE|TDS_ROW_NULLALLOWED so it doesn't cause an issue when an insert/update ignores it.
                row[isIdentity]       = column.RowStatus.HasFlag(RowFormatItemStatus.TDS_ROW_IDENTITY);
                row[isAutoIncrement]  = column.RowStatus.HasFlag(RowFormatItemStatus.TDS_ROW_IDENTITY);
                row[isRowVersion]     = column.RowStatus.HasFlag(RowFormatItemStatus.TDS_ROW_VERSION);
                row[isHidden]         = column.RowStatus.HasFlag(RowFormatItemStatus.TDS_ROW_HIDDEN);
                row[isLong]           = LongTdsTypes.Contains(column.DataType);
                row[isReadOnly]       = !column.RowStatus.HasFlag(RowFormatItemStatus.TDS_ROW_UPDATABLE);
                row[dataTypeName]     = $"{aseDbType}";

                table.Rows.Add(row);

                if (string.IsNullOrEmpty(baseTableNameValue))
                {
                    baseTableNameValue   = column.TableName;
                    baseSchemaNameValue  = column.SchemaName;
                    baseCatalogNameValue = column.CatalogName;
                }
            }

            // Try to load the key info
            //if ((_behavior & CommandBehavior.KeyInfo) == CommandBehavior.KeyInfo)
            {
                if (_command.Connection == null)
                {
                    throw new InvalidOperationException("Invalid AseCommand.Connection");
                }
                if (_command.Connection.State != ConnectionState.Open)
                {
                    throw new InvalidOperationException("Invalid AseCommand.Connection.ConnectionState");
                }

                using (var command = _command.Connection.CreateCommand())
                {
                    command.CommandText = $"{baseCatalogNameValue}..sp_oledb_getindexinfo";
                    command.CommandType = CommandType.StoredProcedure;

                    var tableName = command.CreateParameter();
                    tableName.ParameterName = "@table_name";
                    tableName.AseDbType     = AseDbType.VarChar;
                    tableName.Value         = baseTableNameValue;
                    command.Parameters.Add(tableName);

                    var tableOwner = command.CreateParameter();
                    tableOwner.ParameterName = "@table_owner";
                    tableOwner.AseDbType     = AseDbType.VarChar;
                    tableOwner.Value         = baseSchemaNameValue;
                    command.Parameters.Add(tableOwner);

                    var tableQualifier = command.CreateParameter();
                    tableQualifier.ParameterName = "@table_qualifier";
                    tableQualifier.AseDbType     = AseDbType.VarChar;
                    tableQualifier.Value         = baseCatalogNameValue;
                    command.Parameters.Add(tableQualifier);

                    try
                    {
                        using (var keyInfoDataReader = command.ExecuteReader())
                        {
                            while (keyInfoDataReader.Read())
                            {
                                var keyColumnName  = keyInfoDataReader["COLUMN_NAME"].ToString();
                                var keySchemaName  = keyInfoDataReader["TABLE_SCHEMA"].ToString();
                                var keyCatalogName = keyInfoDataReader["TABLE_CATALOG"].ToString();

                                foreach (DataRow row in table.Rows)
                                {
                                    // Use the base column name in case the column is aliased.
                                    if (
                                        string.Equals(keyColumnName, row[baseColumnName].ToString(),
                                                      StringComparison.OrdinalIgnoreCase) &&
                                        string.Equals(keySchemaName, row[baseSchemaName].ToString(),
                                                      StringComparison.OrdinalIgnoreCase) &&
                                        string.Equals(keyCatalogName, row[baseCatalogName].ToString(),
                                                      StringComparison.OrdinalIgnoreCase))
                                    {
                                        row[isKey]    = (bool)keyInfoDataReader["PRIMARY_KEY"];
                                        row[isUnique] = (bool)keyInfoDataReader["UNIQUE"];
                                    }
                                }
                            }
                        }
                    }
                    catch
                    {
                        // ignored
                    }
                }
            }

            _currentSchemaTable = table;
        }