public TypeDefinition(Type type) { if (DefinitionCache.ContainsKey(type)) { Definition = DefinitionCache[type]; return; } Definition = new DefinitionCacheItem(); ParseType(type); DefinitionCache[type] = Definition; }
/// <summary> /// Loads the necessary command definitions to create a backing table and /// perform CRUD operations with models. /// </summary> private void LoadDefinitions() { var dbSetType = GetType(); if (DefinitionCache.ContainsKey(dbSetType)) { var cache = DefinitionCache[dbSetType]; TableName = cache.TableName; TableDefinition = cache.TableDefinition; SelectDefinition = cache.SelectDefinition; InsertDefinition = cache.InsertDefinition; UpdateDefinition = cache.UpdateDefinition; DeleteDefinition = cache.DeleteDefinition; return; } var createBuilder = new StringBuilder(); var indexBuilder = new List <string>(); var publicInstanceFlags = BindingFlags.Instance | BindingFlags.Public; var properties = typeof(T).GetProperties(publicInstanceFlags); var propertyNames = new List <string>(); // Start off with the table name var tableName = nameof(T); var tableAttribute = typeof(T).GetTypeInfo().GetCustomAttribute <TableAttribute>(); if (tableAttribute != null) { tableName = tableAttribute.Name; } createBuilder.AppendLine($"CREATE TABLE IF NOT EXISTS [{tableName}] ("); createBuilder.AppendLine($" [{nameof(ILiteModel.RowId)}] INTEGER PRIMARY KEY AUTOINCREMENT,"); foreach (var property in properties) { if (property.Name == nameof(ILiteModel.RowId)) { continue; } if (property.CanWrite == false) { continue; } { // Skip if not mapped var notMappedAttribute = property.GetCustomAttribute <NotMappedAttribute>(); if (notMappedAttribute != null) { continue; } } { // Add to indexes if indexed attribute is ON var indexedAttribute = property.GetCustomAttribute <LiteIndexAttribute>(); if (indexedAttribute != null) { indexBuilder.Add( $"CREATE INDEX IF NOT EXISTS [IX_{tableName}_{property.Name}] ON [{tableName}] ([{property.Name}]);"); } } { // Add to unique indexes if indexed attribute is ON var uniqueIndexAttribute = property.GetCustomAttribute <LiteUniqueAttribute>(); if (uniqueIndexAttribute != null) { indexBuilder.Add( $"CREATE UNIQUE INDEX IF NOT EXISTS [IX_{tableName}_{property.Name}] ON [{tableName}] ([{property.Name}]);"); } } propertyNames.Add(property.Name); var propertyType = property.PropertyType; var isNullable = propertyType.GetTypeInfo().IsGenericType&& propertyType.GetGenericTypeDefinition() == typeof(Nullable <>); if (isNullable) { propertyType = Nullable.GetUnderlyingType(propertyType); } var nullStatement = isNullable ? "NULL" : "NOT NULL"; if (propertyType == typeof(string)) { var stringLength = 4096; { var stringLengthAttribute = property.GetCustomAttribute <StringLengthAttribute>(); if (stringLengthAttribute != null) { stringLength = stringLengthAttribute.MaximumLength; } } isNullable = property.GetCustomAttribute <RequiredAttribute>() == null; nullStatement = isNullable ? "NULL" : "NOT NULL"; if (stringLength != 4096) { var checkLength = $"length({property.Name})<={stringLength}"; createBuilder.AppendLine( $" [{property.Name}] NVARCHAR({stringLength}) {nullStatement} CHECK({checkLength}),"); } else { createBuilder.AppendLine($" [{property.Name}] NVARCHAR({stringLength}) {nullStatement},"); } } else if (propertyType.GetTypeInfo().IsValueType) { if (TypeMappings.ContainsKey(propertyType)) { createBuilder.AppendLine($" [{property.Name}] {TypeMappings[propertyType]} {nullStatement},"); } else { createBuilder.AppendLine($" [{property.Name}] TEXT {nullStatement},"); } } else if (propertyType == typeof(byte[])) { createBuilder.AppendLine($" [{property.Name}] BLOB {nullStatement},"); } } //trim out the extra comma createBuilder.Remove(createBuilder.Length - System.Environment.NewLine.Length - 1, System.Environment.NewLine.Length + 1); createBuilder.AppendLine(); createBuilder.AppendLine($");"); foreach (var indexDdl in indexBuilder) { createBuilder.AppendLine(indexDdl); } var escapedColumnNames = string.Join(", ", propertyNames.Select(p => $"[{p}]").ToArray()); var parameterColumnNames = string.Join(", ", propertyNames.Select(p => $"@{p}").ToArray()); var keyValueColumnNames = string.Join(", ", propertyNames.Select(p => $"[{p}] = @{p}").ToArray()); TableName = tableName; TableDefinition = createBuilder.ToString(); SelectDefinition = $"SELECT [{nameof(ILiteModel.RowId)}], {escapedColumnNames} FROM [{tableName}]"; InsertDefinition = $"INSERT INTO [{tableName}] ({escapedColumnNames}) VALUES ({parameterColumnNames}); SELECT last_insert_rowid();"; UpdateDefinition = $"UPDATE [{tableName}] SET {keyValueColumnNames} WHERE [{nameof(ILiteModel.RowId)}] = @{nameof(ILiteModel.RowId)}"; DeleteDefinition = $"DELETE FROM [{tableName}] WHERE [{nameof(ILiteModel.RowId)}] = @{nameof(ILiteModel.RowId)}"; DefinitionCache[dbSetType] = new DefinitionCacheItem { TableName = TableName, TableDefinition = TableDefinition, SelectDefinition = SelectDefinition, InsertDefinition = InsertDefinition, UpdateDefinition = UpdateDefinition, DeleteDefinition = DeleteDefinition }; }
/// <summary> /// Initializes a new instance of the <see cref="LiteDbSet{T}"/> class. /// </summary> public LiteDbSet() { _tableDefinition = new TypeDefinition(typeof(T)).Definition; }