internal static ModelDefinition GetModelDefinition(this Type modelType) { if (typeModelDefinitionMap.TryGetValue(modelType, out var modelDef)) { return(modelDef); } if (modelType.IsValueType || modelType == typeof(string)) { return(null); } var modelAliasAttr = modelType.FirstAttribute <AliasAttribute>(); var schemaAttr = modelType.FirstAttribute <SchemaAttribute>(); var preCreate = modelType.FirstAttribute <PreCreateTableAttribute>(); var postCreate = modelType.FirstAttribute <PostCreateTableAttribute>(); var preDrop = modelType.FirstAttribute <PreDropTableAttribute>(); var postDrop = modelType.FirstAttribute <PostDropTableAttribute>(); modelDef = new ModelDefinition { ModelType = modelType, Name = modelType.Name, Alias = modelAliasAttr?.Name, Schema = schemaAttr?.Name, PreCreateTableSql = preCreate?.Sql, PostCreateTableSql = postCreate?.Sql, PreDropTableSql = preDrop?.Sql, PostDropTableSql = postDrop?.Sql, }; modelDef.CompositeIndexes.AddRange( modelType.AllAttributes <CompositeIndexAttribute>().ToList()); modelDef.UniqueConstraints.AddRange( modelType.AllAttributes <UniqueConstraintAttribute>().ToList()); var objProperties = modelType.GetProperties( BindingFlags.Public | BindingFlags.Instance).ToList(); var hasPkAttr = objProperties.Any(p => p.HasAttribute <PrimaryKeyAttribute>()); var hasIdField = CheckForIdField(objProperties); var i = 0; foreach (var propertyInfo in objProperties) { if (propertyInfo.GetIndexParameters().Length > 0) { continue; //Is Indexer } var sequenceAttr = propertyInfo.FirstAttribute <SequenceAttribute>(); var computeAttr = propertyInfo.FirstAttribute <ComputeAttribute>(); var computedAttr = propertyInfo.FirstAttribute <ComputedAttribute>(); var customSelectAttr = propertyInfo.FirstAttribute <CustomSelectAttribute>(); var decimalAttribute = propertyInfo.FirstAttribute <DecimalLengthAttribute>(); var belongToAttribute = propertyInfo.FirstAttribute <BelongToAttribute>(); var isFirst = i++ == 0; var isAutoId = propertyInfo.HasAttribute <AutoIdAttribute>(); var isPrimaryKey = (!hasPkAttr && (propertyInfo.Name == OrmLiteConfig.IdField || (!hasIdField && isFirst))) || propertyInfo.HasAttributeNamed(typeof(PrimaryKeyAttribute).Name) || isAutoId; var isRowVersion = propertyInfo.Name == ModelDefinition.RowVersionName && (propertyInfo.PropertyType == typeof(ulong) || propertyInfo.PropertyType == typeof(byte[])); var isNullableType = propertyInfo.PropertyType.IsNullableType(); var isNullable = (!propertyInfo.PropertyType.IsValueType && !propertyInfo.HasAttributeNamed(typeof(RequiredAttribute).Name)) || isNullableType; var propertyType = isNullableType ? Nullable.GetUnderlyingType(propertyInfo.PropertyType) : propertyInfo.PropertyType; Type treatAsType = null; if (propertyType.IsEnumFlags() || propertyType.HasAttribute <EnumAsIntAttribute>()) { treatAsType = Enum.GetUnderlyingType(propertyType); } var aliasAttr = propertyInfo.FirstAttribute <AliasAttribute>(); var indexAttr = propertyInfo.FirstAttribute <IndexAttribute>(); var isIndex = indexAttr != null; var isUnique = isIndex && indexAttr.Unique; var stringLengthAttr = propertyInfo.CalculateStringLength(decimalAttribute); var defaultValueAttr = propertyInfo.FirstAttribute <DefaultAttribute>(); var referencesAttr = propertyInfo.FirstAttribute <ReferencesAttribute>(); var referenceAttr = propertyInfo.FirstAttribute <ReferenceAttribute>(); var fkAttr = propertyInfo.FirstAttribute <ForeignKeyAttribute>(); var customFieldAttr = propertyInfo.FirstAttribute <CustomFieldAttribute>(); var chkConstraintAttr = propertyInfo.FirstAttribute <CheckConstraintAttribute>(); var fieldDefinition = new FieldDefinition { Name = propertyInfo.Name, Alias = aliasAttr?.Name, FieldType = propertyType, FieldTypeDefaultValue = propertyType.GetDefaultValue(), TreatAsType = treatAsType, PropertyInfo = propertyInfo, IsNullable = isNullable, IsPrimaryKey = isPrimaryKey, AutoIncrement = isPrimaryKey && propertyInfo.HasAttribute <AutoIncrementAttribute>(), AutoId = isAutoId, IsIndexed = !isPrimaryKey && isIndex, IsUniqueIndex = isUnique, IsClustered = indexAttr?.Clustered == true, IsNonClustered = indexAttr?.NonClustered == true, IndexName = indexAttr?.Name, IsRowVersion = isRowVersion, IgnoreOnInsert = propertyInfo.HasAttribute <IgnoreOnInsertAttribute>(), IgnoreOnUpdate = propertyInfo.HasAttribute <IgnoreOnUpdateAttribute>(), ReturnOnInsert = propertyInfo.HasAttribute <ReturnOnInsertAttribute>(), FieldLength = stringLengthAttr?.MaximumLength, DefaultValue = defaultValueAttr?.DefaultValue, CheckConstraint = chkConstraintAttr?.Constraint, IsUniqueConstraint = propertyInfo.HasAttribute <UniqueAttribute>(), ForeignKey = fkAttr == null ? referencesAttr != null ? new ForeignKeyConstraint(referencesAttr.Type) : null : new ForeignKeyConstraint(fkAttr.Type, fkAttr.OnDelete, fkAttr.OnUpdate, fkAttr.ForeignKeyName), IsReference = referenceAttr != null && propertyType.IsClass, GetValueFn = propertyInfo.CreateGetter(), SetValueFn = propertyInfo.CreateSetter(), Sequence = sequenceAttr?.Name, IsComputed = computeAttr != null || computedAttr != null || customSelectAttr != null, ComputeExpression = computeAttr != null ? computeAttr.Expression : string.Empty, CustomSelect = customSelectAttr?.Sql, Scale = decimalAttribute?.Scale, BelongToModelName = belongToAttribute?.BelongToTableType.GetModelDefinition().ModelName, CustomFieldDefinition = customFieldAttr?.Sql, IsRefType = propertyType.IsRefType(), }; var isIgnored = propertyInfo.HasAttribute <IgnoreAttribute>() || fieldDefinition.IsReference; if (isIgnored) { modelDef.IgnoredFieldDefinitions.Add(fieldDefinition); } else { modelDef.FieldDefinitions.Add(fieldDefinition); } if (isRowVersion) { modelDef.RowVersion = fieldDefinition; } } modelDef.AfterInit(); Dictionary <Type, ModelDefinition> snapshot, newCache; do { snapshot = typeModelDefinitionMap; newCache = new Dictionary <Type, ModelDefinition>(typeModelDefinitionMap) { [modelType] = modelDef }; } while (!ReferenceEquals( Interlocked.CompareExchange(ref typeModelDefinitionMap, newCache, snapshot), snapshot)); LicenseUtils.AssertValidUsage(LicenseFeature.OrmLite, QuotaType.Tables, typeModelDefinitionMap.Count); return(modelDef); }
internal static ModelDefinition GetModelDefinition(this Type modelType) { ModelDefinition modelDef; if (typeModelDefinitionMap.TryGetValue(modelType, out modelDef)) { return(modelDef); } if (modelType.IsValueType() || modelType == typeof(string)) { return(null); } var modelAliasAttr = modelType.FirstAttribute <AliasAttribute>(); var schemaAttr = modelType.FirstAttribute <SchemaAttribute>(); var preCreate = modelType.FirstAttribute <PreCreateTableAttribute>(); var postCreate = modelType.FirstAttribute <PostCreateTableAttribute>(); var preDrop = modelType.FirstAttribute <PreDropTableAttribute>(); var postDrop = modelType.FirstAttribute <PostDropTableAttribute>(); modelDef = new ModelDefinition { ModelType = modelType, Name = modelType.Name, Alias = modelAliasAttr != null ? modelAliasAttr.Name : null, Schema = schemaAttr != null ? schemaAttr.Name : null, PreCreateTableSql = preCreate != null ? preCreate.Sql : null, PostCreateTableSql = postCreate != null ? postCreate.Sql : null, PreDropTableSql = preDrop != null ? preDrop.Sql : null, PostDropTableSql = postDrop != null ? postDrop.Sql : null, }; modelDef.CompositeIndexes.AddRange( modelType.GetCustomAttributes(typeof(CompositeIndexAttribute), true).ToList() .ConvertAll(x => (CompositeIndexAttribute)x)); var objProperties = modelType.GetProperties( BindingFlags.Public | BindingFlags.Instance).ToList(); var hasPkAttr = objProperties.Any(p => p.HasAttribute <PrimaryKeyAttribute>()); var hasIdField = CheckForIdField(objProperties); var i = 0; foreach (var propertyInfo in objProperties) { if (propertyInfo.GetIndexParameters().Length > 0) { continue; //Is Indexer } var sequenceAttr = propertyInfo.FirstAttribute <SequenceAttribute>(); var computeAttr = propertyInfo.FirstAttribute <ComputeAttribute>(); var decimalAttribute = propertyInfo.FirstAttribute <DecimalLengthAttribute>(); var belongToAttribute = propertyInfo.FirstAttribute <BelongToAttribute>(); var isFirst = i++ == 0; var isPrimaryKey = (!hasPkAttr && (propertyInfo.Name == OrmLiteConfig.IdField || (!hasIdField && isFirst))) || propertyInfo.HasAttributeNamed(typeof(PrimaryKeyAttribute).Name); var isRowVersion = propertyInfo.Name == ModelDefinition.RowVersionName && propertyInfo.PropertyType == typeof(ulong); var isNullableType = IsNullableType(propertyInfo.PropertyType); var isNullable = (!propertyInfo.PropertyType.IsValueType && !propertyInfo.HasAttributeNamed(typeof(RequiredAttribute).Name)) || isNullableType; var propertyType = isNullableType ? Nullable.GetUnderlyingType(propertyInfo.PropertyType) : propertyInfo.PropertyType; Type treatAsType = null; if (propertyType.IsEnumFlags()) { treatAsType = Enum.GetUnderlyingType(propertyType); } if (propertyType == typeof(TimeSpan)) { treatAsType = typeof(long); } var aliasAttr = propertyInfo.FirstAttribute <AliasAttribute>(); var indexAttr = propertyInfo.FirstAttribute <IndexAttribute>(); var isIndex = indexAttr != null; var isUnique = isIndex && indexAttr.Unique; var stringLengthAttr = propertyInfo.CalculateStringLength(decimalAttribute); var defaultValueAttr = propertyInfo.FirstAttribute <DefaultAttribute>(); var referencesAttr = propertyInfo.FirstAttribute <ReferencesAttribute>(); var referenceAttr = propertyInfo.FirstAttribute <ReferenceAttribute>(); var foreignKeyAttr = propertyInfo.FirstAttribute <ForeignKeyAttribute>(); var customFieldAttr = propertyInfo.FirstAttribute <CustomFieldAttribute>(); List <Type> autoIncrementTypes = new List <Type>() { typeof(long), typeof(Int32), typeof(Int64) }; var fieldDefinition = new FieldDefinition { Name = propertyInfo.Name, Alias = aliasAttr != null ? aliasAttr.Name : null, FieldType = propertyType, TreatAsType = treatAsType, PropertyInfo = propertyInfo, IsNullable = isNullable, IsPrimaryKey = isPrimaryKey, AutoIncrement = (isPrimaryKey && propertyInfo.HasAttributeNamed(typeof(AutoIncrementAttribute).Name)) || (propertyInfo.Name == "Id" && autoIncrementTypes.Contains(propertyInfo.PropertyType)) || (propertyInfo.Name == "AutoIncrmId" && !modelType.Name.EndsWith("History") && propertyInfo.HasAttributeNamed(typeof(AutoIncrementAttribute).Name) && autoIncrementTypes.Contains(propertyInfo.PropertyType)), IsIndexed = isIndex, IsUnique = isUnique, IsClustered = indexAttr != null && indexAttr.Clustered, IsNonClustered = indexAttr != null && indexAttr.NonClustered, IsRowVersion = isRowVersion, FieldLength = stringLengthAttr != null ? stringLengthAttr.MaximumLength : (int?)null, DefaultValue = defaultValueAttr != null ? defaultValueAttr.DefaultValue : null, ForeignKey = foreignKeyAttr == null ? referencesAttr != null ? new ForeignKeyConstraint(referencesAttr.Type) : null : new ForeignKeyConstraint(foreignKeyAttr.Type, foreignKeyAttr.OnDelete, foreignKeyAttr.OnUpdate, foreignKeyAttr.ForeignKeyName), IsReference = referenceAttr != null && propertyType.IsClass, GetValueFn = propertyInfo.GetPropertyGetterFn(), SetValueFn = propertyInfo.GetPropertySetterFn(), Sequence = sequenceAttr != null ? sequenceAttr.Name : string.Empty, IsComputed = computeAttr != null, ComputeExpression = computeAttr != null ? computeAttr.Expression : string.Empty, Scale = decimalAttribute != null ? decimalAttribute.Scale : (int?)null, BelongToModelName = belongToAttribute != null?belongToAttribute.BelongToTableType.GetModelDefinition().ModelName : null, CustomFieldDefinition = customFieldAttr != null ? customFieldAttr.Sql : null, IsRefType = propertyType.IsRefType(), }; var isIgnored = propertyInfo.HasAttributeNamed(typeof(IgnoreAttribute).Name) || fieldDefinition.IsReference; if (isIgnored) { modelDef.IgnoredFieldDefinitions.Add(fieldDefinition); } else { modelDef.FieldDefinitions.Add(fieldDefinition); } if (isRowVersion) { modelDef.RowVersion = fieldDefinition; } } modelDef.AfterInit(); Dictionary <Type, ModelDefinition> snapshot, newCache; do { snapshot = typeModelDefinitionMap; newCache = new Dictionary <Type, ModelDefinition>(typeModelDefinitionMap); newCache[modelType] = modelDef; } while (!ReferenceEquals( Interlocked.CompareExchange(ref typeModelDefinitionMap, newCache, snapshot), snapshot)); LicenseUtils.AssertValidUsage(LicenseFeature.OrmLite, QuotaType.Tables, typeModelDefinitionMap.Count); return(modelDef); }
internal static ModelDefinition GetModelDefinition(this Type modelType) { ModelDefinition modelDef; if (typeModelDefinitionMap.TryGetValue(modelType, out modelDef)) return modelDef; if (modelType.IsValueType() || modelType == typeof(string)) return null; var modelAliasAttr = modelType.FirstAttribute<AliasAttribute>(); var schemaAttr = modelType.FirstAttribute<SchemaAttribute>(); var preCreate = modelType.FirstAttribute<PreCreateTableAttribute>(); var postCreate = modelType.FirstAttribute<PostCreateTableAttribute>(); var preDrop = modelType.FirstAttribute<PreDropTableAttribute>(); var postDrop = modelType.FirstAttribute<PostDropTableAttribute>(); modelDef = new ModelDefinition { ModelType = modelType, Name = modelType.Name, Alias = modelAliasAttr != null ? modelAliasAttr.Name : null, Schema = schemaAttr != null ? schemaAttr.Name : null, PreCreateTableSql = preCreate != null ? preCreate.Sql : null, PostCreateTableSql = postCreate != null ? postCreate.Sql : null, PreDropTableSql = preDrop != null ? preDrop.Sql : null, PostDropTableSql = postDrop != null ? postDrop.Sql : null, }; modelDef.CompositeIndexes.AddRange( modelType.GetCustomAttributes(typeof(CompositeIndexAttribute), true).ToList() .ConvertAll(x => (CompositeIndexAttribute)x)); var objProperties = modelType.GetProperties( BindingFlags.Public | BindingFlags.Instance).ToList(); var hasPkAttr = objProperties.Any(p => p.HasAttribute<PrimaryKeyAttribute>()); var hasIdField = CheckForIdField(objProperties); var i = 0; foreach (var propertyInfo in objProperties) { if (propertyInfo.GetIndexParameters().Length > 0) continue; //Is Indexer var sequenceAttr = propertyInfo.FirstAttribute<SequenceAttribute>(); var computeAttr = propertyInfo.FirstAttribute<ComputeAttribute>(); var decimalAttribute = propertyInfo.FirstAttribute<DecimalLengthAttribute>(); var belongToAttribute = propertyInfo.FirstAttribute<BelongToAttribute>(); var isFirst = i++ == 0; var isPrimaryKey = (!hasPkAttr && (propertyInfo.Name == OrmLiteConfig.IdField || (!hasIdField && isFirst))) || propertyInfo.HasAttributeNamed(typeof(PrimaryKeyAttribute).Name); var isRowVersion = propertyInfo.Name == ModelDefinition.RowVersionName && propertyInfo.PropertyType == typeof(ulong); var isNullableType = IsNullableType(propertyInfo.PropertyType); var isNullable = (!propertyInfo.PropertyType.IsValueType && !propertyInfo.HasAttributeNamed(typeof(RequiredAttribute).Name)) || isNullableType; var propertyType = isNullableType ? Nullable.GetUnderlyingType(propertyInfo.PropertyType) : propertyInfo.PropertyType; Type treatAsType = null; if (propertyType.IsEnumFlags() || propertyType.HasAttribute<EnumAsIntAttribute>()) treatAsType = Enum.GetUnderlyingType(propertyType); var aliasAttr = propertyInfo.FirstAttribute<AliasAttribute>(); var indexAttr = propertyInfo.FirstAttribute<IndexAttribute>(); var isIndex = indexAttr != null; var isUnique = isIndex && indexAttr.Unique; var stringLengthAttr = propertyInfo.CalculateStringLength(decimalAttribute); var defaultValueAttr = propertyInfo.FirstAttribute<DefaultAttribute>(); var referencesAttr = propertyInfo.FirstAttribute<ReferencesAttribute>(); var referenceAttr = propertyInfo.FirstAttribute<ReferenceAttribute>(); var foreignKeyAttr = propertyInfo.FirstAttribute<ForeignKeyAttribute>(); var customFieldAttr = propertyInfo.FirstAttribute<CustomFieldAttribute>(); var fieldDefinition = new FieldDefinition { Name = propertyInfo.Name, Alias = aliasAttr != null ? aliasAttr.Name : null, FieldType = propertyType, FieldTypeDefaultValue = propertyType.GetDefaultValue(), TreatAsType = treatAsType, PropertyInfo = propertyInfo, IsNullable = isNullable, IsPrimaryKey = isPrimaryKey, AutoIncrement = isPrimaryKey && propertyInfo.HasAttributeNamed(typeof(AutoIncrementAttribute).Name), IsIndexed = !isPrimaryKey && isIndex, IsUnique = isUnique, IsClustered = indexAttr != null && indexAttr.Clustered, IsNonClustered = indexAttr != null && indexAttr.NonClustered, IsRowVersion = isRowVersion, FieldLength = stringLengthAttr != null ? stringLengthAttr.MaximumLength : (int?)null, DefaultValue = defaultValueAttr != null ? defaultValueAttr.DefaultValue : null, ForeignKey = foreignKeyAttr == null ? referencesAttr != null ? new ForeignKeyConstraint(referencesAttr.Type) : null : new ForeignKeyConstraint(foreignKeyAttr.Type, foreignKeyAttr.OnDelete, foreignKeyAttr.OnUpdate, foreignKeyAttr.ForeignKeyName), IsReference = referenceAttr != null && propertyType.IsClass, GetValueFn = propertyInfo.GetPropertyGetterFn(), SetValueFn = propertyInfo.GetPropertySetterFn(), Sequence = sequenceAttr != null ? sequenceAttr.Name : string.Empty, IsComputed = computeAttr != null, ComputeExpression = computeAttr != null ? computeAttr.Expression : string.Empty, Scale = decimalAttribute != null ? decimalAttribute.Scale : (int?)null, BelongToModelName = belongToAttribute != null ? belongToAttribute.BelongToTableType.GetModelDefinition().ModelName : null, CustomFieldDefinition = customFieldAttr != null ? customFieldAttr.Sql : null, IsRefType = propertyType.IsRefType(), }; var isIgnored = propertyInfo.HasAttributeNamed(typeof(IgnoreAttribute).Name) || fieldDefinition.IsReference; if (isIgnored) modelDef.IgnoredFieldDefinitions.Add(fieldDefinition); else modelDef.FieldDefinitions.Add(fieldDefinition); if (isRowVersion) modelDef.RowVersion = fieldDefinition; } modelDef.AfterInit(); Dictionary<Type, ModelDefinition> snapshot, newCache; do { snapshot = typeModelDefinitionMap; newCache = new Dictionary<Type, ModelDefinition>(typeModelDefinitionMap); newCache[modelType] = modelDef; } while (!ReferenceEquals( Interlocked.CompareExchange(ref typeModelDefinitionMap, newCache, snapshot), snapshot)); LicenseUtils.AssertValidUsage(LicenseFeature.OrmLite, QuotaType.Tables, typeModelDefinitionMap.Count); return modelDef; }
internal static ModelDefinition GetModelDefinition(this Type modelType) { if (typeModelDefinitionMap.TryGetValue(modelType, out var modelDef)) { return(modelDef); } if (modelType.IsValueType || modelType == typeof(string)) { return(null); } var modelAliasAttr = modelType.FirstAttribute <AliasAttribute>(); var schemaAttr = modelType.FirstAttribute <SchemaAttribute>(); var preCreates = modelType.AllAttributes <PreCreateTableAttribute>(); var postCreates = modelType.AllAttributes <PostCreateTableAttribute>(); var preDrops = modelType.AllAttributes <PreDropTableAttribute>(); var postDrops = modelType.AllAttributes <PostDropTableAttribute>(); string JoinSql(List <string> statements) { if (statements.Count == 0) { return(null); } var sb = StringBuilderCache.Allocate(); foreach (var sql in statements) { if (sb.Length > 0) { sb.AppendLine(";"); } sb.Append(sql); } var to = StringBuilderCache.ReturnAndFree(sb); return(to); } modelDef = new ModelDefinition { ModelType = modelType, Name = modelType.Name, Alias = modelAliasAttr?.Name, Schema = schemaAttr?.Name, PreCreateTableSql = JoinSql(preCreates.Map(x => x.Sql)), PostCreateTableSql = JoinSql(postCreates.Map(x => x.Sql)), PreDropTableSql = JoinSql(preDrops.Map(x => x.Sql)), PostDropTableSql = JoinSql(postDrops.Map(x => x.Sql)), }; modelDef.CompositeIndexes.AddRange( modelType.AllAttributes <CompositeIndexAttribute>().ToList()); modelDef.UniqueConstraints.AddRange( modelType.AllAttributes <UniqueConstraintAttribute>().ToList()); var objProperties = modelType.GetProperties( BindingFlags.Public | BindingFlags.Instance).ToList(); var hasPkAttr = objProperties.Any(p => p.HasAttributeCached <PrimaryKeyAttribute>()); var hasIdField = CheckForIdField(objProperties); var i = 0; var propertyInfoIdx = 0; foreach (var propertyInfo in objProperties) { if (propertyInfo.GetIndexParameters().Length > 0) { continue; //Is Indexer } var sequenceAttr = propertyInfo.FirstAttribute <SequenceAttribute>(); var computeAttr = propertyInfo.FirstAttribute <ComputeAttribute>(); var computedAttr = propertyInfo.FirstAttribute <ComputedAttribute>(); var persistedAttr = propertyInfo.FirstAttribute <PersistedAttribute>(); var customSelectAttr = propertyInfo.FirstAttribute <CustomSelectAttribute>(); var decimalAttribute = propertyInfo.FirstAttribute <DecimalLengthAttribute>(); var belongToAttribute = propertyInfo.FirstAttribute <BelongToAttribute>(); var referenceAttr = propertyInfo.FirstAttribute <ReferenceAttribute>(); var referenceFieldAttr = propertyInfo.FirstAttribute <ReferenceFieldAttribute>(); var isRowVersion = propertyInfo.Name == ModelDefinition.RowVersionName && (propertyInfo.PropertyType == typeof(ulong) || propertyInfo.PropertyType == typeof(byte[])); var isNullableType = propertyInfo.PropertyType.IsNullableType(); var isNullable = (!propertyInfo.PropertyType.IsValueType && !propertyInfo.HasAttributeNamed(nameof(RequiredAttribute))) || isNullableType; var propertyType = isNullableType ? Nullable.GetUnderlyingType(propertyInfo.PropertyType) : propertyInfo.PropertyType; Type treatAsType = null; if (propertyType.IsEnum) { var enumKind = Converters.EnumConverter.GetEnumKind(propertyType); if (enumKind == EnumKind.Int) { treatAsType = Enum.GetUnderlyingType(propertyType); } else if (enumKind == EnumKind.Char) { treatAsType = typeof(char); } } var isReference = referenceAttr != null || referenceFieldAttr != null; var isIgnored = propertyInfo.HasAttributeCached <IgnoreAttribute>() || isReference; var isFirst = !isIgnored && i++ == 0; var isAutoId = propertyInfo.HasAttributeCached <AutoIdAttribute>(); var isPrimaryKey = (!hasPkAttr && (propertyInfo.Name == OrmLiteConfig.IdField || (!hasIdField && isFirst))) || propertyInfo.HasAttributeNamed(nameof(PrimaryKeyAttribute)) || isAutoId; var isAutoIncrement = isPrimaryKey && propertyInfo.HasAttributeCached <AutoIncrementAttribute>(); if (isAutoIncrement && propertyInfo.PropertyType == typeof(Guid)) { throw new NotSupportedException($"[AutoIncrement] is only valid for integer properties for {modelType.Name}.{propertyInfo.Name} Guid property use [AutoId] instead"); } if (isAutoId && (propertyInfo.PropertyType == typeof(int) || propertyInfo.PropertyType == typeof(long))) { throw new NotSupportedException($"[AutoId] is only valid for Guid properties for {modelType.Name}.{propertyInfo.Name} integer property use [AutoIncrement] instead"); } var aliasAttr = propertyInfo.FirstAttribute <AliasAttribute>(); var indexAttr = propertyInfo.FirstAttribute <IndexAttribute>(); var isIndex = indexAttr != null; var isUnique = isIndex && indexAttr.Unique; var stringLengthAttr = propertyInfo.CalculateStringLength(decimalAttribute); var defaultValueAttr = propertyInfo.FirstAttribute <DefaultAttribute>(); var referencesAttr = propertyInfo.FirstAttribute <ReferencesAttribute>(); var fkAttr = propertyInfo.FirstAttribute <ForeignKeyAttribute>(); var customFieldAttr = propertyInfo.FirstAttribute <CustomFieldAttribute>(); var chkConstraintAttr = propertyInfo.FirstAttribute <CheckConstraintAttribute>(); var order = propertyInfoIdx++; if (customFieldAttr != null) { order = customFieldAttr.Order; } var fieldDefinition = new FieldDefinition { ModelDef = modelDef, Name = propertyInfo.Name, Alias = aliasAttr?.Name, FieldType = propertyType, FieldTypeDefaultValue = isNullable ? null : propertyType.GetDefaultValue(), TreatAsType = treatAsType, PropertyInfo = propertyInfo, IsNullable = isNullable, IsPrimaryKey = isPrimaryKey, AutoIncrement = isPrimaryKey && isAutoIncrement, AutoId = isAutoId, IsIndexed = !isPrimaryKey && isIndex, IsUniqueIndex = isUnique, IsClustered = indexAttr?.Clustered == true, IsNonClustered = indexAttr?.NonClustered == true, IndexName = indexAttr?.Name, IsRowVersion = isRowVersion, IgnoreOnInsert = propertyInfo.HasAttributeCached <IgnoreOnInsertAttribute>(), IgnoreOnUpdate = propertyInfo.HasAttributeCached <IgnoreOnUpdateAttribute>(), ReturnOnInsert = propertyInfo.HasAttributeCached <ReturnOnInsertAttribute>(), FieldLength = stringLengthAttr?.MaximumLength, DefaultValue = defaultValueAttr?.DefaultValue, CheckConstraint = chkConstraintAttr?.Constraint, IsUniqueConstraint = propertyInfo.HasAttributeCached <UniqueAttribute>(), ForeignKey = fkAttr == null ? referencesAttr != null ? new ForeignKeyConstraint(referencesAttr.Type) : null : new ForeignKeyConstraint(fkAttr.Type, fkAttr.OnDelete, fkAttr.OnUpdate, fkAttr.ForeignKeyName), IsReference = isReference, GetValueFn = propertyInfo.CreateGetter(), SetValueFn = propertyInfo.CreateSetter(), Sequence = sequenceAttr?.Name, IsComputed = computeAttr != null || computedAttr != null || customSelectAttr != null, IsPersisted = persistedAttr != null, ComputeExpression = computeAttr != null ? computeAttr.Expression : string.Empty, CustomSelect = customSelectAttr?.Sql, CustomInsert = propertyInfo.FirstAttribute <CustomInsertAttribute>()?.Sql, CustomUpdate = propertyInfo.FirstAttribute <CustomUpdateAttribute>()?.Sql, Scale = decimalAttribute?.Scale, BelongToModelName = belongToAttribute?.BelongToTableType.GetModelDefinition().ModelName, CustomFieldDefinition = customFieldAttr?.Sql, IsRefType = propertyType.IsRefType(), Order = order }; if (referenceFieldAttr != null) { fieldDefinition.FieldReference = new FieldReference(fieldDefinition) { RefModel = referenceFieldAttr.Model, RefId = referenceFieldAttr.Id, RefField = referenceFieldAttr.Field ?? propertyInfo.Name, }; } if (isIgnored) { modelDef.IgnoredFieldDefinitions.Add(fieldDefinition); } else { modelDef.FieldDefinitions.Add(fieldDefinition); } if (isRowVersion) { modelDef.RowVersion = fieldDefinition; } } modelDef.AfterInit(); Dictionary <Type, ModelDefinition> snapshot, newCache; do { snapshot = typeModelDefinitionMap; newCache = new Dictionary <Type, ModelDefinition>(typeModelDefinitionMap) { [modelType] = modelDef }; } while (!ReferenceEquals( Interlocked.CompareExchange(ref typeModelDefinitionMap, newCache, snapshot), snapshot)); LicenseUtils.AssertValidUsage(LicenseFeature.OrmLite, QuotaType.Tables, typeModelDefinitionMap.Count); return(modelDef); }