Exemplo n.º 1
0
 public void Save()
 {
     lock (_sync)
     {
         CurrentSchema.ToJsonFile(CurrentSchema.File);
     }
 }
Exemplo n.º 2
0
 public SchemaResult SetForeignKey(string targetTable, string referencingTable, string referencingColumn, string referencedKey = null, INameFormatter nameFormatter = null)
 {
     try
     {
         Table  table  = CurrentSchema.GetTable(referencingTable);
         Table  target = CurrentSchema.GetTable(targetTable);
         Column col    = table[referencingColumn];
         if (col.DataType == DataTypes.Int || col.DataType == DataTypes.Long)
         {
             ForeignKeyColumn fk = new ForeignKeyColumn(col, targetTable)
             {
                 ReferencedKey   = referencedKey ?? (target.Key != null ? target.Key.Name : "Id"),
                 ReferencedTable = target.Name
             };
             if (nameFormatter != null)
             {
                 fk.ReferencedClass  = nameFormatter.FormatClassName(targetTable);
                 fk.ReferencingClass = nameFormatter.FormatClassName(referencingTable);
                 fk.TableClassName   = nameFormatter.FormatClassName(fk.TableName);
                 fk.PropertyName     = nameFormatter.FormatPropertyName(fk.TableName, fk.Name);
             }
             return(SetForeignKey(table, target, fk));
         }
         else
         {
             throw new InvalidOperationException("The specified column must be a number type");
         }
     }
     catch (Exception ex)
     {
         return(GetErrorResult(ex));
     }
 }
Exemplo n.º 3
0
 /// <summary>
 /// Locates an element given an element locator.
 /// </summary>
 /// <param name="ElementLocator">
 /// The locator specifying the element to find.
 /// </param>
 /// <returns>
 /// The element referenced by the locator; null if the element cannot be found.
 /// </returns>
 /// <remarks>
 /// This method should most likely be moved into a class which wraps <see cref="Element"/>
 /// collections with a value-added wrapper class.
 /// </remarks>
 private Element LocateElement(Locator ElementLocator)
 {
     foreach (XbrlSchema CurrentSchema in this.ValidatedFragment.Schemas)
     {
         var FoundElement = CurrentSchema.LocateElement(ElementLocator);
         if (FoundElement != null)
         {
             return(FoundElement);
         }
     }
     return(null);
 }
Exemplo n.º 4
0
 /// <summary>
 /// Gets the data type for the supplied attribute.
 /// </summary>
 /// <param name="attribute">
 /// The attribute whose data type is returned.
 /// </param>
 /// <returns>
 /// The data type of the supplied attribute. A null reference will be returned
 /// if no matching element can be found for the supplied attribute.
 /// </returns>
 internal AnyType GetAttributeType(IAttribute attribute)
 {
     foreach (var CurrentSchema in SchemaList)
     {
         var matchingAttributeType = CurrentSchema.GetAttributeType(attribute);
         if (matchingAttributeType != null)
         {
             return(matchingAttributeType);
         }
     }
     return(null);
 }
Exemplo n.º 5
0
 /// <summary>
 /// Locates and element using an element locator.
 /// </summary>
 /// <param name="ElementLocator">
 /// A locator for the element to be found.
 /// </param>
 /// <returns>
 /// A reference to the matching element. A null reference will be returned
 /// if no matching element can be found.
 /// </returns>
 internal Element LocateElement(Locator ElementLocator)
 {
     foreach (var CurrentSchema in SchemaList)
     {
         var matchingElement = CurrentSchema.LocateElement(ElementLocator);
         if (matchingElement != null)
         {
             return(matchingElement);
         }
     }
     return(null);
 }
Exemplo n.º 6
0
 /// <summary>
 /// Finds the <see cref="RoleType"/> object having the given ID.
 /// </summary>
 /// <param name="RoleTypeId">
 /// The ID of the role type to find.
 /// </param>
 /// <returns>
 /// The <see cref="RoleType"/> object having the given ID, or null if no
 /// object can be found.
 /// </returns>
 internal RoleType GetRoleType(string RoleTypeId)
 {
     foreach (var CurrentSchema in SchemaList)
     {
         var matchingRoleType = CurrentSchema.GetRoleType(RoleTypeId);
         if (matchingRoleType != null)
         {
             return(matchingRoleType);
         }
     }
     return(null);
 }
Exemplo n.º 7
0
 /// <summary>
 /// Gets the schema containing the element with the given local name.
 /// </summary>
 /// <param name="elementLocalName">
 /// The local name of the element to be found.
 /// </param>
 /// <returns>
 /// A reference to the schema containing the element. A null reference will be returned
 /// if no matching element can be found.
 /// </returns>
 public XbrlSchema GetSchemaContainingElement(string elementLocalName)
 {
     foreach (var CurrentSchema in SchemaList)
     {
         var FoundElement = CurrentSchema.GetElement(elementLocalName);
         if (FoundElement != null)
         {
             return(CurrentSchema);
         }
     }
     return(null);
 }
Exemplo n.º 8
0
 protected virtual SchemaResult SetForeignKey(Table table, Table target, ForeignKeyColumn fk)
 {
     CurrentSchema.AddForeignKey(fk);
     table.RemoveColumn(fk.Name);
     table.AddColumn(fk);
     target.ReferencingForeignKeys = GetReferencingForeignKeysForTable(target.Name);
     table.ForeignKeys             = GetForeignKeysForTable(table.Name);
     if (AutoSave)
     {
         CurrentSchema.Save();
     }
     return(new SchemaResult("ForeignKeyColumn set"));
 }
Exemplo n.º 9
0
 public SchemaResult SetKeyColumn(string tableName, string columnName)
 {
     try
     {
         Table table = CurrentSchema.GetTable(tableName);
         table.SetKeyColumn(columnName);
         if (AutoSave)
         {
             CurrentSchema.Save();
         }
         return(new SchemaResult("Key column set"));
     }
     catch (Exception ex)
     {
         return(GetErrorResult(ex));
     }
 }
Exemplo n.º 10
0
 /// <summary>
 /// Add the specified column to the specified table.
 /// </summary>
 /// <param name="tableName"></param>
 /// <param name="column"></param>
 /// <returns></returns>
 public SchemaResult AddColumn(string tableName, Column column)
 {
     try
     {
         Table table = CurrentSchema.GetTable(tableName);
         table.AddColumn(column);
         if (AutoSave)
         {
             CurrentSchema.Save();
         }
         return(new SchemaResult("column added"));
     }
     catch (Exception ex)
     {
         return(GetErrorResult(ex));
     }
 }
Exemplo n.º 11
0
 /// <summary>
 /// Used to specify a different property name to use
 /// on generated Dao instead of the column name
 /// </summary>
 /// <param name="tableName"></param>
 /// <param name="columnName"></param>
 /// <param name="propertyName"></param>
 /// <returns></returns>
 public SchemaResult SetColumnPropertyName(string tableName, string columnName, string propertyName)
 {
     try
     {
         Table table = CurrentSchema.GetTable(tableName);
         table.SetPropertyName(columnName, propertyName);
         if (AutoSave)
         {
             CurrentSchema.Save();
         }
         return(new SchemaResult("column property name set"));
     }
     catch (Exception ex)
     {
         return(GetErrorResult(ex));
     }
 }
Exemplo n.º 12
0
 protected void SetForeignKeyClassNames()
 {
     CurrentSchema.Tables.Each(table =>
     {
         ForeignKeyColumn[] referencingKeys = GetReferencingForeignKeysForTable(table.Name);
         referencingKeys.Each(fk =>
         {
             fk.ReferencedClass = table.ClassName;
         });
         ForeignKeyColumn[] fks = GetForeignKeysForTable(table.Name);
         fks.Each(fk =>
         {
             fk.ReferencingClass = table.ClassName;
             fk.TableClassName   = table.ClassName;
         });
         if (AutoSave)
         {
             CurrentSchema.Save();
         }
     });
 }
Exemplo n.º 13
0
        internal static Fact Create(XbrlFragment ParentFragment, INode FactNode)
        {
            Fact FactToReturn = null;

            if ((IsXbrlNamespace(FactNode.NamespaceURI) == false) &&
                (IsW3Namespace(FactNode.NamespaceURI) == false) &&
                (FactNode.IsComment == false))
            {
                // This item could be a fact, or it could be a tuple. Examine the schemas
                // to find out what we're dealing with.

                Element MatchingElement = null;
                foreach (var CurrentSchema in ParentFragment.Schemas)
                {
                    var FoundElement = CurrentSchema.GetElement(FactNode.LocalName);
                    if (FoundElement != null)
                    {
                        MatchingElement = FoundElement;
                    }
                }
                if (MatchingElement != null)
                {
                    switch (MatchingElement.SubstitutionGroup)
                    {
                    case Element.ElementSubstitutionGroup.Item:
                        FactToReturn = new Item(ParentFragment, FactNode);
                        break;

                    case Element.ElementSubstitutionGroup.Tuple:
                        FactToReturn = new Tuple(ParentFragment, FactNode);
                        break;

                    default:
                        // This type is unknown, so leave it alone.
                        break;
                    }
                }
            }
            return(FactToReturn);
        }
Exemplo n.º 14
0
 public SchemaResult SetTableClassName(string tableName, string className)
 {
     try
     {
         Table table = CurrentSchema.GetTable(tableName);
         table.ClassName = className;
         table.Columns.Each(col =>
         {
             col.TableClassName = className;
         });
         SetForeignKeyClassNames();
         if (AutoSave)
         {
             CurrentSchema.Save();
         }
         return(new SchemaResult("class name set"));
     }
     catch (Exception ex)
     {
         return(GetErrorResult(ex));
     }
 }
Exemplo n.º 15
0
        private async Task <DatabaseSchema> Load(bool forceReload, CancellationToken cancellationToken)
        {
            Instant requested = TimeHelpers.Clock.Now;

            using (await _lock.LockAsync(cancellationToken).ConfigureAwait(false))
            {
                // Check to see if the currently loaded schema is acceptable.
                CurrentSchema current = _current;

                // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                if ((current != null) &&
                    (!forceReload || (current.Loaded > requested)))
                {
                    // Rethrow load errors.
                    if (current.ExceptionDispatchInfo != null)
                    {
                        current.ExceptionDispatchInfo.Throw();
                    }

                    Debug.Assert(current.Schema != null);
                    return(this);
                }

                // Create dictionaries
                Dictionary <int, SqlSchema>  sqlSchemas  = new Dictionary <int, SqlSchema>();
                Dictionary <int, SqlType>    typesByID   = new Dictionary <int, SqlType>();
                Dictionary <string, SqlType> typesByName =
                    new Dictionary <string, SqlType>(StringComparer.InvariantCultureIgnoreCase);
                Dictionary <string, SqlProgramDefinition> programDefinitions =
                    new Dictionary <string, SqlProgramDefinition>(StringComparer.InvariantCultureIgnoreCase);
                Dictionary <string, SqlTableDefinition> tables =
                    new Dictionary <string, SqlTableDefinition>(StringComparer.InvariantCultureIgnoreCase);

                try
                {
                    // Open a connection
                    using (SqlConnection sqlConnection = new SqlConnection(ConnectionString))
                    {
                        // ReSharper disable once PossibleNullReferenceException
                        await sqlConnection.OpenAsync(cancellationToken).ConfigureAwait(false);

                        Version version;
                        if (!Version.TryParse(sqlConnection.ServerVersion, out version))
                        {
                            throw new DatabaseSchemaException(
                                      () => Resources.DatabaseSchema_Load_CouldNotParseVersionInformation);
                        }
                        Debug.Assert(version != null);

                        if (version.Major < 9)
                        {
                            throw new DatabaseSchemaException(
                                      () => Resources.DatabaseSchema_Load_VersionNotSupported,
                                      version);
                        }

                        string sql = version.Major == 9 ? SQLResources.RetrieveSchema9 : SQLResources.RetrieveSchema10;

                        // Create the command first, as we will reuse on each connection.
                        using (
                            SqlCommand command = new SqlCommand(sql, sqlConnection)
                        {
                            CommandType = CommandType.Text
                        })
                            // Execute command
                            using (SqlDataReader reader =
                                       // ReSharper disable once PossibleNullReferenceException
                                       await
                                       command.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken)
                                       .ConfigureAwait(false))
                            {
                                /*
                                 * Load SQL Schemas
                                 */
                                while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                                {
                                    SqlSchema sqlSchema = new SqlSchema(reader.GetInt32(0), reader.GetString(1));
                                    sqlSchemas.Add(sqlSchema.ID, sqlSchema);
                                }

                                if (sqlSchemas.Count < 1)
                                {
                                    throw new DatabaseSchemaException(
                                              () => Resources.DatabaseSchema_Load_CouldNotRetrieveSchemas);
                                }

                                /*
                                 * Load types
                                 */
                                if (!(await reader.NextResultAsync(cancellationToken).ConfigureAwait(false)))
                                {
                                    throw new DatabaseSchemaException(
                                              () => Resources.DatabaseSchema_Load_RanOutOfResultsRetrievingTypes);
                                }

                                while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                                {
                                    int       schemaId = reader.GetInt32(0);
                                    SqlSchema sqlSchema;
                                    if (!sqlSchemas.TryGetValue(schemaId, out sqlSchema) ||
                                        (sqlSchema == null))
                                    {
                                        throw new DatabaseSchemaException(
                                                  () => Resources.DatabaseSchema_Load_CouldNotFindSchema,
                                                  schemaId);
                                    }
                                    int     id   = reader.GetInt32(1);
                                    string  name = reader.GetString(2).ToLower();
                                    SqlType baseType;
                                    if (reader.IsDBNull(3))
                                    {
                                        baseType = null;
                                    }
                                    else
                                    {
                                        // NB SQL returns types in dependency order
                                        // i.e. base types are always seen first, so this code is much easier.
                                        int baseId = reader.GetInt32(3);
                                        typesByID.TryGetValue(baseId, out baseType);
                                    }

                                    short maxLength     = reader.GetInt16(4);
                                    byte  precision     = reader.GetByte(5);
                                    byte  scale         = reader.GetByte(6);
                                    bool  isNullable    = reader.GetBoolean(7);
                                    bool  isUserDefined = reader.GetBoolean(8);
                                    bool  isCLR         = reader.GetBoolean(9);
                                    bool  isTable       = reader.GetBoolean(10);

                                    // Create type
                                    SqlType type = isTable
                                    ? new SqlTableType(
                                        baseType,
                                        sqlSchema,
                                        name,
                                        new SqlTypeSize(maxLength, precision, scale),
                                        isNullable,
                                        isUserDefined,
                                        isCLR)
                                    : new SqlType(
                                        baseType,
                                        sqlSchema,
                                        name,
                                        new SqlTypeSize(maxLength, precision, scale),
                                        isNullable,
                                        isUserDefined,
                                        isCLR);

                                    // Add to dictionary
                                    typesByName.Add(type.FullName, type);
                                    if (!typesByName.ContainsKey(type.Name))
                                    {
                                        typesByName.Add(type.Name, type);
                                    }
                                    typesByID.Add(id, type);
                                }

                                if (typesByName.Count < 1)
                                {
                                    throw new DatabaseSchemaException(
                                              () => Resources.DatabaseSchema_Load_CouldNotRetrieveTypes);
                                }

                                /*
                                 * Load program definitions
                                 */
                                if (!(await reader.NextResultAsync(cancellationToken).ConfigureAwait(false)))
                                {
                                    throw new DatabaseSchemaException(
                                              () => Resources.DatabaseSchema_Load_RanOutOfResultsRetrievingPrograms);
                                }

                                List <ProgramDefinitionData> programDefinitionData = new List <ProgramDefinitionData>();
                                while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                                {
                                    SqlObjectType type;
                                    string        typeString = reader.GetString(0) ?? string.Empty;
                                    if (!ExtendedEnum <SqlObjectType> .TryParse(typeString, true, out type))
                                    {
                                        throw new DatabaseSchemaException(
                                                  () => Resources.DatabaseSchema_Load_CouldNotFindTypeWhenLoadingPrograms,
                                                  typeString);
                                    }

                                    int       schemaId = reader.GetInt32(1);
                                    SqlSchema sqlSchema;
                                    if (!sqlSchemas.TryGetValue(schemaId, out sqlSchema))
                                    {
                                        throw new DatabaseSchemaException(
                                                  () => Resources.DatabaseSchema_Load_CouldNotFindSchemaWhenLoadingPrograms,
                                                  schemaId);
                                    }
                                    string name = reader.GetString(2).ToLower();

                                    // If we have a null ordinal, we have no parameters.
                                    if (reader.IsDBNull(3))
                                    {
                                        programDefinitionData.Add(new ProgramDefinitionData(type, schemaId, name));
                                        continue;
                                    }

                                    int     ordinal       = reader.GetInt32(3);
                                    string  parameterName = reader.GetString(4).ToLower();
                                    int     typeId        = reader.GetInt32(5);
                                    SqlType parameterType;
                                    if (!typesByID.TryGetValue(typeId, out parameterType) ||
                                        (parameterType == null))
                                    {
                                        throw new DatabaseSchemaException(
                                                  () => Resources.DatabaseSchema_Load_ParameterTypeNotFound,
                                                  parameterName,
                                                  typeId,
                                                  name);
                                    }

                                    short       maxLength     = reader.GetInt16(6);
                                    byte        precision     = reader.GetByte(7);
                                    byte        scale         = reader.GetByte(8);
                                    SqlTypeSize parameterSize = new SqlTypeSize(maxLength, precision, scale);

                                    bool isOutput = reader.GetBoolean(9);
                                    ParameterDirection parameterDirection;
                                    if (!isOutput)
                                    {
                                        parameterDirection = ParameterDirection.Input;
                                    }
                                    else if (parameterName == string.Empty)
                                    {
                                        parameterDirection = ParameterDirection.ReturnValue;
                                    }
                                    else
                                    {
                                        parameterDirection = ParameterDirection.InputOutput;
                                    }

                                    bool parameterIsReadOnly = reader.GetBoolean(10);
                                    programDefinitionData.Add(
                                        new ProgramDefinitionData(
                                            type,
                                            schemaId,
                                            name,
                                            ordinal,
                                            parameterName,
                                            parameterType,
                                            parameterSize,
                                            parameterDirection,
                                            parameterIsReadOnly));
                                }

                                // Create unique program definitions.
                                foreach (SqlProgramDefinition program in programDefinitionData
                                         // ReSharper disable once PossibleNullReferenceException
                                         .GroupBy(d => d.ToString())
                                         .Select(
                                             g =>
                                {
                                    Debug.Assert(g != null);

                                    // Get columns ordered by ordinal.
                                    SqlProgramParameter[] parameters = g
                                                                       // ReSharper disable once PossibleNullReferenceException
                                                                       .Select(d => d.Parameter)
                                                                       .Where(p => p != null)
                                                                       .OrderBy(p => p.Ordinal)
                                                                       .ToArray();

                                    ProgramDefinitionData first = g.First();
                                    Debug.Assert(first != null);
                                    Debug.Assert(first.Name != null);

                                    Debug.Assert(sqlSchemas != null);

                                    SqlSchema sqlSchema;
                                    if (!sqlSchemas.TryGetValue(first.SchemaID, out sqlSchema))
                                    {
                                        throw new DatabaseSchemaException(
                                            () =>
                                            Resources
                                            .DatabaseSchema_Load_CouldNotFindSchemaLoadingTablesAndViews,
                                            first.SchemaID);
                                    }
                                    Debug.Assert(sqlSchema != null);

                                    return(new SqlProgramDefinition(
                                               first.Type,
                                               sqlSchema,
                                               first.Name,
                                               parameters));
                                }))
                                {
                                    Debug.Assert(program != null);
                                    programDefinitions[program.FullName] = program;

                                    if (!programDefinitions.ContainsKey(program.Name))
                                    {
                                        programDefinitions.Add(program.Name, program);
                                    }
                                }

                                /*
                                 * Load tables and views
                                 */
                                if (!(await reader.NextResultAsync(cancellationToken).ConfigureAwait(false)))
                                {
                                    throw new DatabaseSchemaException(
                                              () => Resources.DatabaseSchema_Load_RanOutOfTablesAndViews);
                                }

                                // Read raw data in.
                                List <TableDefinitionData> tableDefinitionData = new List <TableDefinitionData>();
                                while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                                {
                                    SqlObjectType type;
                                    string        typeString = reader.GetString(0) ?? string.Empty;
                                    if (!ExtendedEnum <SqlObjectType> .TryParse(typeString, true, out type))
                                    {
                                        throw new DatabaseSchemaException(
                                                  () => Resources.DatabaseSchema_Load_CouldNotFindObjectType,
                                                  typeString);
                                    }
                                    int     schemaId   = reader.GetInt32(1);
                                    string  name       = reader.GetString(2).ToLower();
                                    int     ordinal    = reader.GetInt32(3);
                                    string  columnName = reader.GetString(4).ToLower();
                                    int     typeId     = reader.GetInt32(5);
                                    SqlType sqlType;
                                    if (!typesByID.TryGetValue(typeId, out sqlType) ||
                                        (sqlType == null))
                                    {
                                        throw new DatabaseSchemaException(
                                                  () => Resources.DatabaseSchema_Load_ColumnTypeNotFound,
                                                  columnName,
                                                  typeId,
                                                  name);
                                    }

                                    short       maxLength   = reader.GetInt16(6);
                                    byte        precision   = reader.GetByte(7);
                                    byte        scale       = reader.GetByte(8);
                                    SqlTypeSize sqlTypeSize = new SqlTypeSize(maxLength, precision, scale);

                                    bool isNullable = reader.GetBoolean(9);

                                    int?tableType = reader.IsDBNull(10) ? null : (int?)reader.GetInt32(10);

                                    tableDefinitionData.Add(
                                        new TableDefinitionData(
                                            type,
                                            schemaId,
                                            name,
                                            ordinal,
                                            columnName,
                                            sqlType,
                                            sqlTypeSize,
                                            isNullable,
                                            tableType));
                                }

                                // Create unique table definitions.
                                foreach (SqlTableDefinition table in tableDefinitionData
                                         // ReSharper disable once PossibleNullReferenceException
                                         .GroupBy(d => d.ToString())
                                         .Select(
                                             g =>
                                {
                                    Debug.Assert(g != null);

                                    // Get columns ordered by ordinal.
                                    SqlColumn[] columns = g
                                                          // ReSharper disable PossibleNullReferenceException
                                                          .Select(d => d.Column)
                                                          .OrderBy(c => c.Ordinal)
                                                          // ReSharper restore PossibleNullReferenceException
                                                          .ToArray();
                                    Debug.Assert(columns.Length > 0);

                                    TableDefinitionData first = g.First();
                                    Debug.Assert(first != null);
                                    Debug.Assert(first.Name != null);
                                    Debug.Assert(sqlSchemas != null);

                                    SqlSchema sqlSchema;
                                    if (!sqlSchemas.TryGetValue(first.SchemaID, out sqlSchema))
                                    {
                                        throw new DatabaseSchemaException(
                                            () =>
                                            Resources
                                            .DatabaseSchema_Load_CouldNotFindSchemaLoadingTablesAndViews,
                                            first.SchemaID);
                                    }
                                    Debug.Assert(sqlSchema != null);

                                    SqlTableType tableType;
                                    if (first.TableTypeID != null)
                                    {
                                        Debug.Assert(typesByID != null);

                                        SqlType tType;
                                        if (!typesByID.TryGetValue(first.TableTypeID.Value, out tType))
                                        {
                                            throw new DatabaseSchemaException(
                                                () => Resources.DatabaseSchema_Load_TableTypeNotFound,
                                                first.TableTypeID.Value,
                                                first.Name);
                                        }
                                        tableType = tType as SqlTableType;
                                        if (tableType == null)
                                        {
                                            throw new DatabaseSchemaException(
                                                () => Resources.DatabaseSchema_Load_TypeNotTableType,
                                                first.TableTypeID.Value,
                                                first.Name);
                                        }
                                    }
                                    else
                                    {
                                        tableType = null;
                                    }

                                    return(new SqlTableDefinition(
                                               first.Type,
                                               sqlSchema,
                                               first.Name,
                                               columns,
                                               tableType));
                                }))
                                {
                                    Debug.Assert(table != null);
                                    tables[table.FullName] = table;

                                    if (!tables.ContainsKey(table.Name))
                                    {
                                        tables.Add(table.Name, table);
                                    }
                                }
                            }
                    }

                    // Update the current schema.
                    _current = new CurrentSchema(Schema.GetOrAdd(sqlSchemas, programDefinitions, tables, typesByName));

                    // Always return this
                    return(this);
                }
                // In the event of an error we don't set the loaded flag - this allows retries.
                catch (DatabaseSchemaException databaseSchemaException)
                {
                    // Capture the exception in the current schema.
                    _current = new CurrentSchema(ExceptionDispatchInfo.Capture(databaseSchemaException));
                    throw;
                }
                catch (Exception exception)
                {
                    // Wrap exception in Database exception.
                    DatabaseSchemaException databaseSchemaException = new DatabaseSchemaException(
                        exception,
                        LoggingLevel.Critical,
                        () => Resources.DatabaseSchema_Load_ErrorOccurred);
                    // Capture the exception in the current schema.
                    _current = new CurrentSchema(ExceptionDispatchInfo.Capture(databaseSchemaException));
                    throw databaseSchemaException;
                }
            }
        }
Exemplo n.º 16
0
 public Table GetTable(string tableName)
 {
     return(CurrentSchema.GetTable(tableName));
 }
Exemplo n.º 17
0
 public XrefTable GetXref(string tableName)
 {
     return(CurrentSchema.GetXref(tableName));
 }
Exemplo n.º 18
0
 public void RemoveTable(string tableName)
 {
     CurrentSchema.RemoveTable(tableName);
 }
Exemplo n.º 19
0
        private async Task<DatabaseSchema> Load(bool forceReload, CancellationToken cancellationToken)
        {
            Instant requested = TimeHelpers.Clock.Now;
            using (await _lock.LockAsync(cancellationToken).ConfigureAwait(false))
            {
                // Check to see if the currently loaded schema is acceptable.
                CurrentSchema current = _current;

                // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                if ((current != null) &&
                    (!forceReload || (current.Loaded > requested)))
                {
                    // Rethrow load errors.
                    if (current.ExceptionDispatchInfo != null)
                        current.ExceptionDispatchInfo.Throw();

                    Debug.Assert(current.Schema != null);
                    return this;
                }

                // Create dictionaries
                Dictionary<int, SqlSchema> sqlSchemas = new Dictionary<int, SqlSchema>();
                Dictionary<int, SqlType> typesByID = new Dictionary<int, SqlType>();
                Dictionary<string, SqlType> typesByName =
                    new Dictionary<string, SqlType>(StringComparer.InvariantCultureIgnoreCase);
                Dictionary<string, SqlProgramDefinition> programDefinitions =
                    new Dictionary<string, SqlProgramDefinition>(StringComparer.InvariantCultureIgnoreCase);
                Dictionary<string, SqlTableDefinition> tables =
                    new Dictionary<string, SqlTableDefinition>(StringComparer.InvariantCultureIgnoreCase);

                try
                {
                    // Open a connection
                    using (SqlConnection sqlConnection = new SqlConnection(ConnectionString))
                    {
                        // ReSharper disable once PossibleNullReferenceException
                        await sqlConnection.OpenAsync(cancellationToken).ConfigureAwait(false);

                        Version version;
                        if (!Version.TryParse(sqlConnection.ServerVersion, out version))
                            throw new DatabaseSchemaException(
                                () => Resources.DatabaseSchema_Load_CouldNotParseVersionInformation);
                        Debug.Assert(version != null);

                        if (version.Major < 9)
                            throw new DatabaseSchemaException(
                                () => Resources.DatabaseSchema_Load_VersionNotSupported,
                                version);

                        string sql = version.Major == 9 ? SQLResources.RetrieveSchema9 : SQLResources.RetrieveSchema10;

                        // Create the command first, as we will reuse on each connection.
                        using (
                            SqlCommand command = new SqlCommand(sql, sqlConnection) { CommandType = CommandType.Text })
                            // Execute command
                        using (SqlDataReader reader =
                            // ReSharper disable once PossibleNullReferenceException
                            await
                                command.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken)
                                    .ConfigureAwait(false))
                        {
                            /*
                             * Load SQL Schemas
                             */
                            while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                            {
                                SqlSchema sqlSchema = new SqlSchema(reader.GetInt32(0), reader.GetString(1));
                                sqlSchemas.Add(sqlSchema.ID, sqlSchema);
                            }

                            if (sqlSchemas.Count < 1)
                                throw new DatabaseSchemaException(
                                    () => Resources.DatabaseSchema_Load_CouldNotRetrieveSchemas);

                            /*
                             * Load types
                             */
                            if (!(await reader.NextResultAsync(cancellationToken).ConfigureAwait(false)))
                                throw new DatabaseSchemaException(
                                    () => Resources.DatabaseSchema_Load_RanOutOfResultsRetrievingTypes);

                            while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                            {
                                int schemaId = reader.GetInt32(0);
                                SqlSchema sqlSchema;
                                if (!sqlSchemas.TryGetValue(schemaId, out sqlSchema) ||
                                    (sqlSchema == null))
                                    throw new DatabaseSchemaException(
                                        () => Resources.DatabaseSchema_Load_CouldNotFindSchema,
                                        schemaId);
                                int id = reader.GetInt32(1);
                                string name = reader.GetString(2).ToLower();
                                SqlType baseType;
                                if (reader.IsDBNull(3))
                                    baseType = null;
                                else
                                {
                                    // NB SQL returns types in dependency order
                                    // i.e. base types are always seen first, so this code is much easier.
                                    int baseId = reader.GetInt32(3);
                                    typesByID.TryGetValue(baseId, out baseType);
                                }

                                short maxLength = reader.GetInt16(4);
                                byte precision = reader.GetByte(5);
                                byte scale = reader.GetByte(6);
                                bool isNullable = reader.GetBoolean(7);
                                bool isUserDefined = reader.GetBoolean(8);
                                bool isCLR = reader.GetBoolean(9);
                                bool isTable = reader.GetBoolean(10);

                                // Create type
                                SqlType type = isTable
                                    ? new SqlTableType(
                                        baseType,
                                        sqlSchema,
                                        name,
                                        new SqlTypeSize(maxLength, precision, scale),
                                        isNullable,
                                        isUserDefined,
                                        isCLR)
                                    : new SqlType(
                                        baseType,
                                        sqlSchema,
                                        name,
                                        new SqlTypeSize(maxLength, precision, scale),
                                        isNullable,
                                        isUserDefined,
                                        isCLR);

                                // Add to dictionary
                                typesByName.Add(type.FullName, type);
                                if (!typesByName.ContainsKey(type.Name))
                                    typesByName.Add(type.Name, type);
                                typesByID.Add(id, type);
                            }

                            if (typesByName.Count < 1)
                                throw new DatabaseSchemaException(
                                    () => Resources.DatabaseSchema_Load_CouldNotRetrieveTypes);

                            /*
                             * Load program definitions
                             */
                            if (!(await reader.NextResultAsync(cancellationToken).ConfigureAwait(false)))
                                throw new DatabaseSchemaException(
                                    () => Resources.DatabaseSchema_Load_RanOutOfResultsRetrievingPrograms);

                            List<ProgramDefinitionData> programDefinitionData = new List<ProgramDefinitionData>();
                            while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                            {
                                SqlObjectType type;
                                string typeString = reader.GetString(0) ?? string.Empty;
                                if (!ExtendedEnum<SqlObjectType>.TryParse(typeString, true, out type))
                                    throw new DatabaseSchemaException(
                                        () => Resources.DatabaseSchema_Load_CouldNotFindTypeWhenLoadingPrograms,
                                        typeString);

                                int schemaId = reader.GetInt32(1);
                                SqlSchema sqlSchema;
                                if (!sqlSchemas.TryGetValue(schemaId, out sqlSchema))
                                    throw new DatabaseSchemaException(
                                        () => Resources.DatabaseSchema_Load_CouldNotFindSchemaWhenLoadingPrograms,
                                        schemaId);
                                string name = reader.GetString(2).ToLower();

                                // If we have a null ordinal, we have no parameters.
                                if (reader.IsDBNull(3))
                                {
                                    programDefinitionData.Add(new ProgramDefinitionData(type, schemaId, name));
                                    continue;
                                }

                                int ordinal = reader.GetInt32(3);
                                string parameterName = reader.GetString(4).ToLower();
                                int typeId = reader.GetInt32(5);
                                SqlType parameterType;
                                if (!typesByID.TryGetValue(typeId, out parameterType) ||
                                    (parameterType == null))
                                    throw new DatabaseSchemaException(
                                        () => Resources.DatabaseSchema_Load_ParameterTypeNotFound,
                                        parameterName,
                                        typeId,
                                        name);

                                short maxLength = reader.GetInt16(6);
                                byte precision = reader.GetByte(7);
                                byte scale = reader.GetByte(8);
                                SqlTypeSize parameterSize = new SqlTypeSize(maxLength, precision, scale);

                                bool isOutput = reader.GetBoolean(9);
                                ParameterDirection parameterDirection;
                                if (!isOutput)
                                    parameterDirection = ParameterDirection.Input;
                                else if (parameterName == string.Empty)
                                    parameterDirection = ParameterDirection.ReturnValue;
                                else
                                    parameterDirection = ParameterDirection.InputOutput;

                                bool parameterIsReadOnly = reader.GetBoolean(10);
                                programDefinitionData.Add(
                                    new ProgramDefinitionData(
                                        type,
                                        schemaId,
                                        name,
                                        ordinal,
                                        parameterName,
                                        parameterType,
                                        parameterSize,
                                        parameterDirection,
                                        parameterIsReadOnly));
                            }

                            // Create unique program definitions.
                            foreach (SqlProgramDefinition program in programDefinitionData
                                // ReSharper disable once PossibleNullReferenceException
                                .GroupBy(d => d.ToString())
                                .Select(
                                    g =>
                                    {
                                        Debug.Assert(g != null);

                                        // Get columns ordered by ordinal.
                                        SqlProgramParameter[] parameters = g
                                            // ReSharper disable once PossibleNullReferenceException
                                            .Select(d => d.Parameter)
                                            .Where(p => p != null)
                                            .OrderBy(p => p.Ordinal)
                                            .ToArray();

                                        ProgramDefinitionData first = g.First();
                                        Debug.Assert(first != null);
                                        Debug.Assert(first.Name != null);

                                        Debug.Assert(sqlSchemas != null);

                                        SqlSchema sqlSchema;
                                        if (!sqlSchemas.TryGetValue(first.SchemaID, out sqlSchema))
                                            throw new DatabaseSchemaException(
                                                () =>
                                                    Resources
                                                    .DatabaseSchema_Load_CouldNotFindSchemaLoadingTablesAndViews,
                                                first.SchemaID);
                                        Debug.Assert(sqlSchema != null);

                                        return new SqlProgramDefinition(
                                            first.Type,
                                            sqlSchema,
                                            first.Name,
                                            parameters);
                                    }))
                            {
                                Debug.Assert(program != null);
                                programDefinitions[program.FullName] = program;

                                if (!programDefinitions.ContainsKey(program.Name))
                                    programDefinitions.Add(program.Name, program);
                            }

                            /*
                             * Load tables and views
                             */
                            if (!(await reader.NextResultAsync(cancellationToken).ConfigureAwait(false)))
                                throw new DatabaseSchemaException(
                                    () => Resources.DatabaseSchema_Load_RanOutOfTablesAndViews);

                            // Read raw data in.
                            List<TableDefinitionData> tableDefinitionData = new List<TableDefinitionData>();
                            while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                            {
                                SqlObjectType type;
                                string typeString = reader.GetString(0) ?? string.Empty;
                                if (!ExtendedEnum<SqlObjectType>.TryParse(typeString, true, out type))
                                    throw new DatabaseSchemaException(
                                        () => Resources.DatabaseSchema_Load_CouldNotFindObjectType,
                                        typeString);
                                int schemaId = reader.GetInt32(1);
                                string name = reader.GetString(2).ToLower();
                                int ordinal = reader.GetInt32(3);
                                string columnName = reader.GetString(4).ToLower();
                                int typeId = reader.GetInt32(5);
                                SqlType sqlType;
                                if (!typesByID.TryGetValue(typeId, out sqlType) ||
                                    (sqlType == null))
                                    throw new DatabaseSchemaException(
                                        () => Resources.DatabaseSchema_Load_ColumnTypeNotFound,
                                        columnName,
                                        typeId,
                                        name);

                                short maxLength = reader.GetInt16(6);
                                byte precision = reader.GetByte(7);
                                byte scale = reader.GetByte(8);
                                SqlTypeSize sqlTypeSize = new SqlTypeSize(maxLength, precision, scale);

                                bool isNullable = reader.GetBoolean(9);

                                int? tableType = reader.IsDBNull(10) ? null : (int?)reader.GetInt32(10);

                                tableDefinitionData.Add(
                                    new TableDefinitionData(
                                        type,
                                        schemaId,
                                        name,
                                        ordinal,
                                        columnName,
                                        sqlType,
                                        sqlTypeSize,
                                        isNullable,
                                        tableType));
                            }

                            // Create unique table definitions.
                            foreach (SqlTableDefinition table in tableDefinitionData
                                // ReSharper disable once PossibleNullReferenceException
                                .GroupBy(d => d.ToString())
                                .Select(
                                    g =>
                                    {
                                        Debug.Assert(g != null);

                                        // Get columns ordered by ordinal.
                                        SqlColumn[] columns = g
                                            // ReSharper disable PossibleNullReferenceException
                                            .Select(d => d.Column)
                                            .OrderBy(c => c.Ordinal)
                                            // ReSharper restore PossibleNullReferenceException
                                            .ToArray();
                                        Debug.Assert(columns.Length > 0);

                                        TableDefinitionData first = g.First();
                                        Debug.Assert(first != null);
                                        Debug.Assert(first.Name != null);
                                        Debug.Assert(sqlSchemas != null);

                                        SqlSchema sqlSchema;
                                        if (!sqlSchemas.TryGetValue(first.SchemaID, out sqlSchema))
                                            throw new DatabaseSchemaException(
                                                () =>
                                                    Resources
                                                    .DatabaseSchema_Load_CouldNotFindSchemaLoadingTablesAndViews,
                                                first.SchemaID);
                                        Debug.Assert(sqlSchema != null);

                                        SqlTableType tableType;
                                        if (first.TableTypeID != null)
                                        {
                                            Debug.Assert(typesByID != null);

                                            SqlType tType;
                                            if (!typesByID.TryGetValue(first.TableTypeID.Value, out tType))
                                                throw new DatabaseSchemaException(
                                                    () => Resources.DatabaseSchema_Load_TableTypeNotFound,
                                                    first.TableTypeID.Value,
                                                    first.Name);
                                            tableType = tType as SqlTableType;
                                            if (tableType == null)
                                                throw new DatabaseSchemaException(
                                                    () => Resources.DatabaseSchema_Load_TypeNotTableType,
                                                    first.TableTypeID.Value,
                                                    first.Name);
                                        }
                                        else tableType = null;

                                        return new SqlTableDefinition(
                                            first.Type,
                                            sqlSchema,
                                            first.Name,
                                            columns,
                                            tableType);
                                    }))
                            {
                                Debug.Assert(table != null);
                                tables[table.FullName] = table;

                                if (!tables.ContainsKey(table.Name))
                                    tables.Add(table.Name, table);
                            }
                        }
                    }

                    // Update the current schema.
                    _current = new CurrentSchema(Schema.GetOrAdd(sqlSchemas, programDefinitions, tables, typesByName));

                    // Always return this
                    return this;
                }
                    // In the event of an error we don't set the loaded flag - this allows retries.
                catch (DatabaseSchemaException databaseSchemaException)
                {
                    // Capture the exception in the current schema.
                    _current = new CurrentSchema(ExceptionDispatchInfo.Capture(databaseSchemaException));
                    throw;
                }
                catch (Exception exception)
                {
                    // Wrap exception in Database exception.
                    DatabaseSchemaException databaseSchemaException = new DatabaseSchemaException(
                        exception,
                        LoggingLevel.Critical,
                        () => Resources.DatabaseSchema_Load_ErrorOccurred);
                    // Capture the exception in the current schema.
                    _current = new CurrentSchema(ExceptionDispatchInfo.Capture(databaseSchemaException));
                    throw databaseSchemaException;
                }
            }
        }