private ICollection<EntityDescriptor.Attribute> GetForeignKeys(EntityDescriptor entityDescriptor) { IEnumerator<EntityDescriptor.Relationship> oneToManyRealtionships = entityDescriptor.GetManyToOneRelationships(); IEnumerator<EntityDescriptor.Relationship> manyToManyRealtionships = entityDescriptor.GetManyToManyRelationships(); ICollection<EntityDescriptor.Attribute> foreignAttributes = new List<EntityDescriptor.Attribute>(); IEnumerator<EntityDescriptor.Attribute> attributes = entityDescriptor.GetAttributes(); while (attributes.MoveNext()) { EntityDescriptor.Attribute attribute = attributes.Current; if (attribute.IsPrimaryKey()) { foreignAttributes.Add(attribute); } } while (oneToManyRealtionships.MoveNext()) { EntityDescriptor.Relationship relationship = oneToManyRealtionships.Current; EntityDescriptor referedEntityDescriptor = relationship.GetReferedEntityDescriptor(); ICollection<EntityDescriptor.Attribute> referedForeignKeys = GetForeignKeys(referedEntityDescriptor); IEnumerator<EntityDescriptor.Attribute> referedForeignKeysIterate = referedForeignKeys.GetEnumerator(); while (referedForeignKeysIterate.MoveNext()) { foreignAttributes.Add(referedForeignKeysIterate.Current); } } while (manyToManyRealtionships.MoveNext()) { EntityDescriptor.Relationship relationship = manyToManyRealtionships.Current; EntityDescriptor referedEntityDescriptor = relationship.GetReferedEntityDescriptor(); ICollection<EntityDescriptor.Attribute> referedForeignKeys = GetForeignKeys(referedEntityDescriptor); IEnumerator<EntityDescriptor.Attribute> referedForeignKeysIterate = referedForeignKeys.GetEnumerator(); while (referedForeignKeysIterate.MoveNext()) { foreignAttributes.Add(referedForeignKeysIterate.Current); } } return foreignAttributes; }
/// <summary> /// Is used to create a new table in an database /// Manually creating table structure using Entity Descriptor mapped class. /// Example: /// <para> /// <code> /// Book book = new Book(); /// /// try { /// Database.CreateTables(book.GetEntityDescriptor()); /// } catch(DatabaseException databaseException) { /// //Log It. /// } /// </code> /// </para> /// </summary> /// <param name="entityDescriptor">Entity Descriptor object which defines the structure of table</param> /// <exception cref="Siminov.Core.Exception.DatabaseException">If not able to create table in SQLite</exception> public static void CreateTable(EntityDescriptor entityDescriptor) { /* * 1. Get IDatabase with respect to current entity descriptor class name. * 2. Get Table Name, and all columns. * 3. Get all attributes and properties from entity descriptor. * LIKE(COLUMN NAMES, COLUMN TYPES, PRIMARY KEYS, UNIQUE's, NOT NULL, DEFAULT VALUES, CHECKS, ). * * 4. If current version of OS is lower then 8 (FROYO) then we have to create triggers for all foreign keys defined, * because Android OS Version lower then 8 (FROYO) does not support FOREIGN KEY SYNTAX. * Else get foreign keys. * * 5. Call QueryBuilder.formCreateTableQuery, get query to create table. * After forming create table query call executeQuery method to create table in database. * * 6. Create all triggers. * 7. Create Index for table if its defined. * Get all attributes and properties of index. * LIKE(INDEX NAME, IS UNIQUE INDEX, COLUMN NAMES). * After forming index query call executeQuery method to create index. * */ DatabaseDescriptor databaseDescriptor = GetDatabaseDescriptor(entityDescriptor.GetClassName()); DatabaseBundle databaseBundle = resourceManager.GetDatabaseBundle(databaseDescriptor.GetDatabaseName()); IDatabaseImpl database = databaseBundle.GetDatabase(); IQueryBuilder queryBuilder = databaseBundle.GetQueryBuilder(); IDataTypeHandler dataTypeHandler = databaseBundle.GetDataTypeHandler(); if (database == null) { Log.Log.Error(typeof(DatabaseHelper).FullName, "CreateTable", "No Database Instance Found For ENITTY-DESCRIPTOR: " + entityDescriptor.GetClassName()); throw new DeploymentException(typeof(DatabaseHelper).FullName, "CreateTable", "No Database Instance Found For ENTITY-DESCRIPTOR: " + entityDescriptor.GetClassName()); } String tableName = entityDescriptor.GetTableName(); /* * Get all attributes and properties from entity descriptor. * LIKE(COLUMN NAMES, COLUMN TYPES, DEFAULT VALUES, CHECKS, NOT NULL, PRIMARY KEYS, UNIQUE's ). */ ICollection<String> columnNames = new LinkedList<String>(); ICollection<String> columnTypes = new LinkedList<String>(); ICollection<String> defaultValues = new LinkedList<String>(); ICollection<String> checks = new LinkedList<String>(); ICollection<Boolean> isNotNull = new LinkedList<Boolean>(); ICollection<String> primaryKeys = new LinkedList<String>(); ICollection<String> uniqueKeys = new LinkedList<String>(); IEnumerator<EntityDescriptor.Attribute> attributes = entityDescriptor.GetAttributes(); while (attributes.MoveNext()) { EntityDescriptor.Attribute attribute = attributes.Current; columnNames.Add(attribute.GetColumnName()); columnTypes.Add(dataTypeHandler.Convert(attribute.GetType())); isNotNull.Add(attribute.IsNotNull()); defaultValues.Add(attribute.GetDefaultValue()); checks.Add(attribute.GetCheck()); bool isPrimary = attribute.IsPrimaryKey(); bool isUnique = attribute.IsUnique(); if (isPrimary) { primaryKeys.Add(attribute.GetColumnName()); } if (isUnique) { uniqueKeys.Add(attribute.GetColumnName()); } } /* * Add ONE-TO-MANY And MANY-TO-MANY Relationship Columns. */ IEnumerator<EntityDescriptor.Relationship> oneToManyRelationships = entityDescriptor.GetManyToOneRelationships(); IEnumerator<EntityDescriptor.Relationship> manyToManyRelationships = entityDescriptor.GetManyToManyRelationships(); while (oneToManyRelationships.MoveNext()) { EntityDescriptor.Relationship oneToManyRelationship = oneToManyRelationships.Current; EntityDescriptor referedEntityDescriptor = oneToManyRelationship.GetReferedEntityDescriptor(); if (referedEntityDescriptor == null) { referedEntityDescriptor = GetEntityDescriptor(oneToManyRelationship.GetReferTo()); oneToManyRelationship.SetReferedEntityDescriptor(referedEntityDescriptor); } ICollection<EntityDescriptor.Attribute> foreignAttributes = GetForeignKeys(referedEntityDescriptor); IEnumerator<EntityDescriptor.Attribute> foreignAttributesIterator = foreignAttributes.GetEnumerator(); while (foreignAttributesIterator.MoveNext()) { EntityDescriptor.Attribute foreignAttribute = foreignAttributesIterator.Current; columnNames.Add(foreignAttribute.GetColumnName()); columnTypes.Add(dataTypeHandler.Convert(foreignAttribute.GetType())); isNotNull.Add(foreignAttribute.IsNotNull()); defaultValues.Add(foreignAttribute.GetDefaultValue()); checks.Add(foreignAttribute.GetCheck()); bool isPrimary = foreignAttribute.IsPrimaryKey(); if (isPrimary) { primaryKeys.Add(foreignAttribute.GetColumnName()); } bool isUnique = foreignAttribute.IsUnique(); if (isUnique) { uniqueKeys.Add(foreignAttribute.GetColumnName()); } } } while (manyToManyRelationships.MoveNext()) { EntityDescriptor.Relationship manyToManyRelationship = manyToManyRelationships.Current; EntityDescriptor parentEntityDescriptor = manyToManyRelationship.GetReferedEntityDescriptor(); IEnumerator<EntityDescriptor.Attribute> parentAttributes = parentEntityDescriptor.GetAttributes(); while (parentAttributes.MoveNext()) { EntityDescriptor.Attribute attribute = parentAttributes.Current; bool isPrimary = attribute.IsPrimaryKey(); if (isPrimary) { columnNames.Add(attribute.GetColumnName()); columnTypes.Add(dataTypeHandler.Convert(attribute.GetType())); isNotNull.Add(attribute.IsNotNull()); defaultValues.Add(attribute.GetDefaultValue()); checks.Add(attribute.GetCheck()); if (isPrimary) { primaryKeys.Add(attribute.GetColumnName()); } bool isUnique = attribute.IsUnique(); if (isUnique) { uniqueKeys.Add(attribute.GetColumnName()); } } } } /* * If current version of OS is lower then 8 (FROYO) then we have to create triggers for all foreign keys defined, * because Android OS Version lower then 8 (FROYO) does not support FOREIGN KEY SYNTAX. * Else get foreign keys. */ String foreignKeys = ""; IDictionary<String, Object> parameters = new Dictionary<String, Object>(); parameters.Add(IQueryBuilder.FORM_FOREIGN_KEYS_DATABASE_DESCRIPTOR_PARAMETER, entityDescriptor); foreignKeys = queryBuilder.FormForeignKeyQuery(parameters); /* * Call QueryBuilder.formCreateTableQuery, get query to create table. * After forming create table query call executeQuery method to create table in database. */ parameters = new Dictionary<String, Object>(); parameters.Add(IQueryBuilder.FORM_CREATE_TABLE_QUERY_TABLE_NAME_PARAMETER, tableName); parameters.Add(IQueryBuilder.FORM_CREATE_TABLE_QUERY_COLUMN_NAMES_PARAMETER, columnNames.GetEnumerator()); parameters.Add(IQueryBuilder.FORM_CREATE_TABLE_QUERY_COLUMN_TYPES_PARAMETER, columnTypes.GetEnumerator()); parameters.Add(IQueryBuilder.FORM_CREATE_TABLE_QUERY_DEFAULT_VALUES_PARAMETER, defaultValues.GetEnumerator()); parameters.Add(IQueryBuilder.FORM_CREATE_TABLE_QUERY_CHECKS_PARAMETER, checks.GetEnumerator()); parameters.Add(IQueryBuilder.FORM_CREATE_TABLE_QUERY_PRIMARY_KEYS_PARAMETER, primaryKeys.GetEnumerator()); parameters.Add(IQueryBuilder.FORM_CREATE_TABLE_QUERY_NOT_NULLS_PARAMETER, isNotNull.GetEnumerator()); parameters.Add(IQueryBuilder.FORM_CREATE_TABLE_QUERY_UNIQUE_COLUMNS_PARAMETER, uniqueKeys.GetEnumerator()); parameters.Add(IQueryBuilder.FORM_CREATE_TABLE_QUERY_FOREIGN_KEYS_PARAMETER, foreignKeys); String query = queryBuilder.FormCreateTableQuery(parameters); database.ExecuteQuery(GetDatabaseDescriptor(entityDescriptor.GetClassName()), entityDescriptor, query); /* * Create Index for table if its defined. */ IEnumerator<EntityDescriptor.Index> indexes = entityDescriptor.GetIndexes(); while (indexes.MoveNext()) { /* * Get all attributes and properties of index. * LIKE(INDEX NAME, IS UNIQUE INDEX, COLUMN NAMES). * * After forming index query call executeQuery method to create index. */ CreateIndex(entityDescriptor, indexes.Current); } IDatabaseEvents databaseEventHandler = resourceManager.GetDatabaseEventHandler(); if (databaseEventHandler != null) { databaseEventHandler.OnTableCreated(GetDatabaseDescriptor(entityDescriptor.GetClassName()), entityDescriptor); } }