public static string GetQuotedColumnName(this IOrmLiteDialectProvider dialect,
     ModelDefinition tableDef, FieldDefinition fieldDef)
 {
     return dialect.GetQuotedTableName(tableDef) +
         "." +
         dialect.GetQuotedColumnName(fieldDef.FieldName);
 }
 /// <summary>
 /// Value from DB to Populate on POCO Data Model
 /// </summary>
 public virtual object FromDbValue(FieldDefinition fieldDef, object value)
 {
     return value;
 }
 /// <summary>
 /// Parameterized Value with FieldDefinition. Optional, Defaults to ToDbValue(Type,object)
 /// </summary>
 public virtual object ToDbValue(FieldDefinition fieldDef, object value)
 {
     return ToDbValue(fieldDef.FieldType, value);
 }
        internal static ModelDefinition GetModelDefinition(this Type modelType)
        {
            ModelDefinition modelDef;
                        
            if (typeModelDefinitionMap.TryGetValue(modelType, out modelDef))
                return modelDef;

            var modelAliasAttr = modelType.FirstAttribute<AliasAttribute>();

            var fromAttr= modelType.FirstAttribute<SelectFromAttribute>();
            string tableAlias; //=null;
            string modelName=null;
            Type fromType=null;
            StringBuilder join = new StringBuilder();
            
            if (fromAttr!=null){
                tableAlias= fromAttr.Alias;
                fromType=  fromAttr.From;
                modelName= fromType.GetModelDefinition().ModelName;
            }
            else if (modelType.BaseType!=typeof(Object)){
                fromType= modelType.BaseType;
                modelName=fromType.GetModelDefinition().ModelName;
                tableAlias= modelName;
            }
            else
                tableAlias=modelAliasAttr != null ? modelAliasAttr.Name : modelType.Name;
            
            //if(fromType!=null){
                
                var joinAttrList = modelType.GetCustomAttributes(typeof(JoinToAttribute), true).ToList()
                    .ConvertAll(x => (JoinToAttribute)x).OrderBy(x=>x.Order).ToList();
                
                foreach(var ja in joinAttrList){
                    string parentField;
                    string childField;

                    FieldDefinition fd;
                    if(ja.Parent==null && fromType==null)
                        fd=null;
                    else 
                        fd= ((ja.Parent!=null)? ja.Parent:fromType).
                        GetModelDefinition().FieldDefinitions.FirstOrDefault(x=>x.Name==ja.ParentProperty);

                    if(fd!=default(FieldDefinition) ) 
                        parentField= fd.FieldName;
                    else
                    {
                        parentField= modelType.GetFieldName(ja.ParentProperty);
                    }
                    
                    fd= ja.Child.GetModelDefinition().FieldDefinitions.FirstOrDefault(x=>x.Name==ja.ChildProperty);
                    if(fd!=default(FieldDefinition) ) 
                        childField= fd.FieldName;
                    else
                        childField= ja.ChildProperty;
                    
                    join.AppendFormat("\n{0} Join {1} {2} on {3}={4}",ja.JoinType,
                        OrmLiteConfig.DialectProvider.GetQuotedName( ja.Child.GetModelDefinition().ModelName),
                        OrmLiteConfig.DialectProvider.GetQuotedName(ja.ChildAlias), 
                        (ja.ParentAlias.IsNullOrEmpty() && tableAlias.IsNullOrEmpty())?
                                  string.Format("{0}",OrmLiteConfig.DialectProvider.GetQuotedName(parentField))
                                  :string.Format("{0}.{1}",
                            OrmLiteConfig.DialectProvider.GetQuotedName(ja.ParentAlias??tableAlias),
                            OrmLiteConfig.DialectProvider.GetQuotedName(parentField)),


                        string.Format("{0}.{1}",
                            OrmLiteConfig.DialectProvider.GetQuotedName(ja.ChildAlias),
                            OrmLiteConfig.DialectProvider.GetQuotedName(childField))
                        );
                }
            //}
            

            var schemaAttr = modelType.FirstAttribute<SchemaAttribute>();
            modelDef = new ModelDefinition
            {
                ModelType = modelType,
                Name = modelName?? modelType.Name,
                Alias = modelAliasAttr != null ? modelAliasAttr.Name : null,
                Schema = schemaAttr != null ? schemaAttr.Name : null,
                TableAlias= tableAlias,
                Join = join.Length==0? null: join.ToString()
            };

            modelDef.CompositeIndexes.AddRange(
                modelType.GetCustomAttributes(typeof(CompositeIndexAttribute), true).ToList()
                .ConvertAll(x => (CompositeIndexAttribute)x));

            var objProperties = modelType.GetProperties(
                BindingFlags.Public | BindingFlags.Instance).ToList();

            var hasIdField = CheckForIdField(objProperties);

            var i = 0;
            foreach (var propertyInfo in objProperties)
            {
                if (propertyInfo.FirstAttribute<IgnoreAttribute>()!=null) continue;
                var sequenceAttr = propertyInfo.FirstAttribute<SequenceAttribute>();
                var computeAttr= propertyInfo.FirstAttribute<ComputeAttribute>();
                var pkAttribute = propertyInfo.FirstAttribute<PrimaryKeyAttribute>();
                var decimalAttribute = propertyInfo.FirstAttribute<DecimalLengthAttribute>();
                var isFirst = i++ == 0;

                var isPrimaryKey = propertyInfo.Name ==OrmLiteConfig.IdField || (!hasIdField && isFirst)
                    || pkAttribute != null;

                var isNullableType = IsNullableType(propertyInfo.PropertyType);

                var isNullable = (!propertyInfo.PropertyType.IsValueType
                                   && propertyInfo.FirstAttribute<RequiredAttribute>() == null)
                                 || isNullableType;

                var propertyType = isNullableType
                    ? Nullable.GetUnderlyingType(propertyInfo.PropertyType)
                    : propertyInfo.PropertyType;

                var aliasAttr = propertyInfo.FirstAttribute<AliasAttribute>();

                var indexAttr = propertyInfo.FirstAttribute<IndexAttribute>();
                var isIndex = indexAttr != null;
                var isUnique = isIndex && indexAttr.Unique;

                var stringLengthAttr = propertyInfo.FirstAttribute<StringLengthAttribute>();

                var defaultValueAttr = propertyInfo.FirstAttribute<DefaultAttribute>();

                var referencesAttr = propertyInfo.FirstAttribute<ReferencesAttribute>();
                
                if(decimalAttribute != null  && stringLengthAttr==null)
                    stringLengthAttr= new StringLengthAttribute(decimalAttribute.Precision);
                
                var belongsToAttr= propertyInfo.FirstAttribute<BelongsToAttribute>();
                
                string fieldAlias=null;
                string belongsToAlias=null;
                string alias=null;
                
                if (belongsToAttr!=null){
                    belongsToAlias= belongsToAttr.ParentAlias;
                    fieldAlias = propertyInfo.Name;
                    var fd= belongsToAttr.Parent.GetModelDefinition().FieldDefinitions.
                        FirstOrDefault(x=>x.Name==(belongsToAttr.PropertyName?? propertyInfo.Name));
                    if(fd!=default(FieldDefinition) ) 
                        alias= fd.FieldName;
                    else alias= propertyInfo.Name ;
                }
                else if(fromType != null && fromType != modelType){
                    var fd= fromType.GetModelDefinition().FieldDefinitions.FirstOrDefault(x=>x.Name==propertyInfo.Name);
                    if(fd!=default(FieldDefinition) ){
                        alias= fd.FieldName;
                        fieldAlias = propertyInfo.Name;
                        belongsToAlias= tableAlias;
                    }
                }
                
                var fieldDefinition = new FieldDefinition
                {
                    Name = propertyInfo.Name,
                    Alias = alias?? (aliasAttr != null ? aliasAttr.Name : null),
                    FieldAlias= fieldAlias,
                    BelongsToAlias= belongsToAlias,
                    FieldType = propertyType,
                    PropertyInfo = propertyInfo,
                    IsNullable = isNullable,
                    IsPrimaryKey = isPrimaryKey,
                    AutoIncrement = isPrimaryKey && propertyInfo.FirstAttribute<AutoIncrementAttribute>() != null,
                    IsIndexed = isIndex,
                    IsUnique = isUnique,
                    FieldLength = stringLengthAttr != null ? stringLengthAttr.MaximumLength : (int?)null,
                    DefaultValue = defaultValueAttr != null ? defaultValueAttr.DefaultValue : null,
                    ReferencesType = referencesAttr != null ? referencesAttr.Type : null,
                    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,
                };

                modelDef.FieldDefinitions.Add(fieldDefinition);
            }
            modelDef.SqlSelectAllFromTable = "SELECT {0} FROM {1}{2}".Fmt(OrmLiteConfig.DialectProvider.GetColumnNames(modelDef),
                OrmLiteConfig.DialectProvider.GetQuotedTableName(modelDef),
                tableAlias.IsNullOrEmpty()?
                    "":
                    OrmLiteConfig.DialectProvider.GetQuotedName(tableAlias));

            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));

            return modelDef;
        }
        internal static ModelDefinition GetModelDefinition(this Type modelType)
        {
            lock (typeModelDefinitionMap)
            {
                ModelDefinition modelDef;
                if (!typeModelDefinitionMap.TryGetValue(modelType, out modelDef))
                {
                    var modelAliasAttr = modelType.FirstAttribute<AliasAttribute>();
                    modelDef = new ModelDefinition {
                        ModelType = modelType,
                        Name = modelType.Name,
                        Alias = modelAliasAttr != null ? modelAliasAttr.Name : null,
                    };

                    modelDef.CompositeIndexes.AddRange(
                        modelType.GetCustomAttributes(typeof(CompositeIndexAttribute), true).ToList()
                        .ConvertAll(x => (CompositeIndexAttribute)x ) );

                    var objProperties = modelType.GetProperties(
                        BindingFlags.Public | BindingFlags.Instance).ToList();

                    var hasIdField = CheckForIdField(objProperties);

                    var i = 0;
                    foreach (var propertyInfo in objProperties)
                    {
                        var isFirst = i++ == 0;

                        var isPrimaryKey = propertyInfo.Name == IdField
                                           || (!hasIdField && isFirst);

                        var isNullableType = IsNullableType(propertyInfo.PropertyType);

                        var isNullable = (!propertyInfo.PropertyType.IsValueType
                                            && propertyInfo.FirstAttribute<RequiredAttribute>() == null)
                                         || isNullableType;

                        var propertyType = isNullableType
                                            ? Nullable.GetUnderlyingType(propertyInfo.PropertyType)
                                            : propertyInfo.PropertyType;

                        var aliasAttr = propertyInfo.FirstAttribute<AliasAttribute>();

                        var indexAttr = propertyInfo.FirstAttribute<IndexAttribute>();
                        var isIndex = indexAttr != null;
                        var isUnique = isIndex && indexAttr.Unique;

                        var stringLengthAttr = propertyInfo.FirstAttribute<StringLengthAttribute>();

                        var defaultValueAttr = propertyInfo.FirstAttribute<DefaultAttribute>();

                        var referencesAttr = propertyInfo.FirstAttribute<ReferencesAttribute>();

                        var fieldDefinition = new FieldDefinition {
                            Name = propertyInfo.Name,
                            Alias = aliasAttr != null ? aliasAttr.Name : null,
                            FieldType = propertyType,
                            PropertyInfo = propertyInfo,
                            IsNullable = isNullable,
                            IsPrimaryKey = isPrimaryKey,
                            AutoIncrement = isPrimaryKey && propertyInfo.FirstAttribute<AutoIncrementAttribute>() != null,
                            IsIndexed = isIndex,
                            IsUnique = isUnique,
                            FieldLength = stringLengthAttr != null ? stringLengthAttr.MaximumLength : (int?)null,
                            DefaultValue = defaultValueAttr != null ? defaultValueAttr.DefaultValue : null,
                            ReferencesType = referencesAttr != null ? referencesAttr.Type : null,
                            ConvertValueFn = OrmLiteConfig.DialectProvider.ConvertDbValue,
                            QuoteValueFn = OrmLiteConfig.DialectProvider.GetQuotedValue,
                            PropertyInvoker = OrmLiteConfig.PropertyInvoker,
                        };

                        modelDef.FieldDefinitions.Add(fieldDefinition);
                    }

                    typeModelDefinitionMap[modelType] = modelDef;
                }

                return modelDef;
            }
        }
        internal static void SetParamValue(this IOrmLiteDialectProvider dialectProvider, IDbDataParameter p, object value, Type propType, FieldDefinition fieldDef = null)
        {
            if (fieldDef != null)
            {
                value = dialectProvider.GetFieldValue(fieldDef, value);
                var valueType = value?.GetType();
                if (valueType != null && valueType != propType)
                {
                    dialectProvider.InitDbParam(p, valueType);
                }
            }
            else
            {
                value = dialectProvider.GetFieldValue(propType, value);
                var valueType = value?.GetType();
                if (valueType != null && valueType != propType)
                {
                    dialectProvider.InitDbParam(p, valueType);
                }
            }

            p.Value = value == null
                ? DBNull.Value
                : p.DbType == DbType.String
                    ? value.ToString()
                    : value;
        }
		public static ModelDefinition GetModelDefinition(this Type modelType)
		{
			ModelDefinition modelDefinition;

			if (_typeModelDefinitionMap.TryGetValue(modelType, out modelDefinition))
				return modelDefinition;

			if (modelType.IsValueType() || modelType == typeof(string))
				return null;

			AliasAttribute aliasAttribute = modelType.FirstAttribute<AliasAttribute>();
			SchemaAttribute schemaAttribute = modelType.FirstAttribute<SchemaAttribute>();
			modelDefinition = new ModelDefinition
			{
				ModelType = modelType,
				Name = modelType.Name,
				Alias = aliasAttribute != null ? aliasAttribute.Name : null,
				Schema = schemaAttribute != null ? schemaAttribute.Name : null
			};

			modelDefinition.CompositeIndexes.AddRange(modelType.GetCustomAttributes(typeof(CompositeIndexAttribute), true).ToList().ConvertAll(x => (CompositeIndexAttribute)x));

			List<PropertyInfo> objProperties = modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();

			bool hasIdField = CheckForIdField(objProperties);

			for (int i = 0; i < objProperties.Count; i++)
			{
				PropertyInfo propertyInfo = objProperties[i];

				SequenceAttribute sequenceAttribute = propertyInfo.FirstAttribute<SequenceAttribute>();
				ComputeAttribute computeAttribute = propertyInfo.FirstAttribute<ComputeAttribute>();
				DecimalLengthAttribute decimalAttribute = propertyInfo.FirstAttribute<DecimalLengthAttribute>();
				BelongToAttribute belongToAttribute = propertyInfo.FirstAttribute<BelongToAttribute>();
				bool isPrimaryKey = propertyInfo.Name == OrmLiteConfig.IdField || (!hasIdField && i == 0) || propertyInfo.HasAttributeNamed(typeof(PrimaryKeyAttribute));
				bool isNullableType = IsNullableType(propertyInfo.PropertyType);
				bool isNullable = (!propertyInfo.PropertyType.IsValueType && !propertyInfo.HasAttributeNamed(typeof(RequiredAttribute))) || isNullableType;
				Type propertyType = isNullableType ? Nullable.GetUnderlyingType(propertyInfo.PropertyType) : propertyInfo.PropertyType;
				aliasAttribute = propertyInfo.FirstAttribute<AliasAttribute>();
				IndexAttribute indexAttribute = propertyInfo.FirstAttribute<IndexAttribute>();
				bool isIndex = indexAttribute != null;
				bool isUnique = isIndex && indexAttribute.Unique;
				StringLengthAttribute stringLengthAttribute = propertyInfo.CalculateStringLength(decimalAttribute);
				DefaultAttribute defaultValueAttribute = propertyInfo.FirstAttribute<DefaultAttribute>();
				ReferencesAttribute referencesAttribute = propertyInfo.FirstAttribute<ReferencesAttribute>();
				//var referenceAttr = propertyInfo.FirstAttribute<ReferenceAttribute>();
				ForeignKeyAttribute foreignKeyAttribute = propertyInfo.FirstAttribute<ForeignKeyAttribute>();

				FieldDefinition fieldDefinition = new FieldDefinition();

				fieldDefinition.Name = propertyInfo.Name;
				fieldDefinition.Alias = aliasAttribute != null ? aliasAttribute.Name : null;
				fieldDefinition.FieldType = propertyType;
				fieldDefinition.PropertyInfo = propertyInfo;
				fieldDefinition.IsNullable = isNullable;
				fieldDefinition.IsPrimaryKey = isPrimaryKey;
				fieldDefinition.AutoIncrement = isPrimaryKey && propertyInfo.HasAttributeNamed(typeof(AutoIncrementAttribute));
				fieldDefinition.IsIndexed = isIndex;
				fieldDefinition.IsUnique = isUnique;
				fieldDefinition.FieldLength = stringLengthAttribute != null ? stringLengthAttribute.MaximumLength : (int?)null;
				fieldDefinition.DefaultValue = defaultValueAttribute != null ? defaultValueAttribute.DefaultValue : null;
				fieldDefinition.ForeignKey = foreignKeyAttribute == null ? referencesAttribute != null ? new ForeignKeyConstraint(referencesAttribute.Type) : null : new ForeignKeyConstraint(foreignKeyAttribute.Type, foreignKeyAttribute.OnDelete, foreignKeyAttribute.OnUpdate, foreignKeyAttribute.ForeignKeyName);
				//fieldDefinition.IsReference = referenceAttr != null && propertyType.IsClass;
				fieldDefinition.GetValueFn = propertyInfo.GetPropertyGetterFn();
				fieldDefinition.SetValueFn = propertyInfo.GetPropertySetterFn();
				fieldDefinition.Sequence = sequenceAttribute != null ? sequenceAttribute.Name : string.Empty;
				fieldDefinition.IsComputed = computeAttribute != null;
				fieldDefinition.ComputeExpression = computeAttribute != null ? computeAttribute.Expression : string.Empty;
				fieldDefinition.Scale = decimalAttribute != null ? decimalAttribute.Scale : (int?)null;
				fieldDefinition.BelongToModelName = belongToAttribute != null ? belongToAttribute.BelongToTableType.GetModelDefinition().ModelName : null;

				var isIgnored = propertyInfo.HasAttributeNamed(typeof(IgnoreAttribute)); // || fieldDefinition.IsReference;
				if (isIgnored)
				{
					modelDefinition.IgnoredFieldDefinitions.Add(fieldDefinition);
				}
				else
				{
					modelDefinition.FieldDefinitions.Add(fieldDefinition);
				}
			}

			//modelDefinition.SqlSelectAllFromTable = "SELECT {0} FROM {1} ".Fmt(OrmLiteConfig.DialectProvider.GetColumnNames(modelDefinition), OrmLiteConfig.DialectProvider.GetQuotedTableName(modelDefinition));

			Dictionary<Type, ModelDefinition> snapshot, newCache;
			do
			{
				snapshot = _typeModelDefinitionMap;
				newCache = new Dictionary<Type, ModelDefinition>(_typeModelDefinitionMap);
				newCache[modelType] = modelDefinition;
			}
			while (!ReferenceEquals(Interlocked.CompareExchange(ref _typeModelDefinitionMap, newCache, snapshot), snapshot));

			return modelDefinition;
		}
示例#8
0
        public string GetForeignKeyName(ModelDefinition modelDef, ModelDefinition refModelDef, INamingStrategy NamingStrategy, FieldDefinition fieldDef)
        {
            if (ForeignKeyName.IsNullOrEmpty())
            {
                var modelName = modelDef.IsInSchema
                    ? modelDef.Schema + "_" + NamingStrategy.GetTableName(modelDef.ModelName)
                    : NamingStrategy.GetTableName(modelDef.ModelName);

                var refModelName = refModelDef.IsInSchema
                    ? refModelDef.Schema + "_" + NamingStrategy.GetTableName(refModelDef.ModelName)
                    : NamingStrategy.GetTableName(refModelDef.ModelName);

                var fkName = string.Format("FK_{0}_{1}_{2}", modelName, refModelName, fieldDef.FieldName);
                return NamingStrategy.ApplyNameRestrictions(fkName);
            }
            else { return ForeignKeyName; }
        }
示例#9
0
 public static string GetQuotedColumnName(this IOrmLiteDialectProvider dialect,
                                          FieldDefinition fieldDef)
 {
     return(dialect.GetQuotedColumnName(fieldDef.FieldName));
 }
        internal static int FindColumnIndex(this IDataReader dataReader, IOrmLiteDialectProvider dialectProvider, FieldDefinition fieldDef)
        {
            var index = NotFound;

            index = dataReader.GetColumnIndex(dialectProvider, fieldDef.FieldName);
            if (index == NotFound)
            {
                index = TryGuessColumnIndex(fieldDef.FieldName, dataReader);
            }
            // Try fallback to original field name when overriden by alias
            if (index == NotFound && fieldDef.Alias != null && !OrmLiteConfig.DisableColumnGuessFallback)
            {
                index = dataReader.GetColumnIndex(dialectProvider, fieldDef.Name);
                if (index == NotFound)
                {
                    index = TryGuessColumnIndex(fieldDef.Name, dataReader);
                }
            }

            return(index);
        }
 public bool IsRefField(FieldDefinition fieldDef)
 {
     return((fieldDef.Alias != null && IsRefField(fieldDef.Alias)) ||
            IsRefField(fieldDef.Name));
 }
示例#12
0
        public static FieldDefinition GetSelfRefFieldDefIfExists(this ModelDefinition modelDef, ModelDefinition refModelDef, FieldDefinition fieldDef)
        {
            var refField = (fieldDef == null ? null
                 : modelDef.FieldDefinitions.FirstOrDefault(x => x.ForeignKey != null && x.ForeignKey.ReferenceType == refModelDef.ModelType &&
                                                            fieldDef.IsSelfRefField(x)))
                           ?? modelDef.FieldDefinitions.FirstOrDefault(x => x.ForeignKey != null && x.ForeignKey.ReferenceType == refModelDef.ModelType)
                           ?? modelDef.FieldDefinitions.FirstOrDefault(refModelDef.IsRefField);

            return(refField);
        }
        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>();

            modelDef = new ModelDefinition {
                ModelType = modelType,
                Name      = modelType.Name,
                Alias     = modelAliasAttr != null ? modelAliasAttr.Name : null,
                Schema    = schemaAttr != null ? schemaAttr.Name : null
            };

            modelDef.CompositeIndexes.AddRange(
                modelType.GetCustomAttributes(typeof(CompositeIndexAttribute), true).ToList()
                .ConvertAll(x => (CompositeIndexAttribute)x));

            var objProperties = modelType.GetProperties(
                BindingFlags.Public | BindingFlags.Instance).ToList();

            var hasIdField = CheckForIdField(objProperties);

            var i = 0;

            foreach (var propertyInfo in objProperties)
            {
                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 = propertyInfo.Name == OrmLiteConfig.IdField || (!hasIdField && isFirst) ||
                                   propertyInfo.HasAttributeNamed(typeof(PrimaryKeyAttribute).Name);

                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;

                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 fieldDefinition = new FieldDefinition {
                    Name          = propertyInfo.Name,
                    Alias         = aliasAttr != null ? aliasAttr.Name : null,
                    FieldType     = propertyType,
                    PropertyInfo  = propertyInfo,
                    IsNullable    = isNullable,
                    IsPrimaryKey  = isPrimaryKey,
                    AutoIncrement =
                        isPrimaryKey &&
                        propertyInfo.HasAttributeNamed(typeof(AutoIncrementAttribute).Name),
                    IsIndexed   = isIndex,
                    IsUnique    = isUnique,
                    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,
                };

                var isIgnored = propertyInfo.HasAttributeNamed(typeof(IgnoreAttribute).Name) ||
                                fieldDefinition.IsReference;
                if (isIgnored)
                {
                    modelDef.IgnoredFieldDefinitions.Add(fieldDefinition);
                }
                else
                {
                    modelDef.FieldDefinitions.Add(fieldDefinition);
                }
            }

            modelDef.SqlSelectAllFromTable = "SELECT {0} FROM {1} "
                                             .Fmt(OrmLiteConfig.DialectProvider.GetColumnNames(modelDef),
                                                  OrmLiteConfig.DialectProvider.GetQuotedTableName(modelDef));

            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);
        }
 public bool IsSelfRefField(FieldDefinition fieldDef)
 {
     return (fieldDef.Alias != null && IsSelfRefField(fieldDef.Alias))
             || IsSelfRefField(fieldDef.Name);
 }
        public FieldDefinition Clone(Action<FieldDefinition> modifier = null)
        {
            var fieldDef = new FieldDefinition
            {
                Name = Name,
                Alias = Alias,
                FieldType = FieldType,
                FieldTypeDefaultValue = FieldTypeDefaultValue,
                TreatAsType = TreatAsType,
                PropertyInfo = PropertyInfo,
                IsPrimaryKey = IsPrimaryKey,
                AutoIncrement = AutoIncrement,
                IsNullable = IsNullable,
                IsIndexed = IsIndexed,
                IsUnique = IsUnique,
                IsClustered = IsClustered,
                IsNonClustered = IsNonClustered,
                IsRowVersion = IsRowVersion,
                FieldLength = FieldLength,
                Scale = Scale,
                DefaultValue = DefaultValue,
                ForeignKey = ForeignKey,
                GetValueFn = GetValueFn,
                SetValueFn = SetValueFn,
                Sequence = Sequence,
                IsComputed = IsComputed,
                ComputeExpression = ComputeExpression,
                CustomSelect = CustomSelect,
                BelongToModelName = BelongToModelName,
                IsReference = IsReference,
                CustomFieldDefinition = CustomFieldDefinition,
                IsRefType = IsRefType,
            };

            modifier?.Invoke(fieldDef);
            return fieldDef;
        }
        internal static ModelDefinition GetModelDefinition(this Type modelType)
        {
            ModelDefinition modelDef;

            if (typeModelDefinitionMap.TryGetValue(modelType, out modelDef))
                return modelDef;

            var modelAliasAttr = modelType.FirstAttribute<AliasAttribute>();
            var schemaAttr = modelType.FirstAttribute<SchemaAttribute>();
            modelDef = new ModelDefinition {
                ModelType = modelType,
                Name = modelType.Name,
                Alias = modelAliasAttr != null ? modelAliasAttr.Name : null,
                Schema = schemaAttr != null ? schemaAttr.Name : null
            };

            modelDef.CompositeIndexes.AddRange(
                modelType.GetCustomAttributes(typeof(CompositeIndexAttribute), true).ToList()
                .ConvertAll(x => (CompositeIndexAttribute)x));

            var objProperties = modelType.GetProperties(
                BindingFlags.Public | BindingFlags.Instance).ToList();

            var hasIdField = CheckForIdField(objProperties);

            var i = 0;
            foreach (var propertyInfo in objProperties)
            {
                var sequenceAttr = propertyInfo.FirstAttribute<SequenceAttribute>();
                var computeAttr= propertyInfo.FirstAttribute<ComputeAttribute>();
                var pkAttribute = propertyInfo.FirstAttribute<PrimaryKeyAttribute>();
                var decimalAttribute = propertyInfo.FirstAttribute<DecimalLengthAttribute>();
                var belongToAttribute = propertyInfo.FirstAttribute<BelongToAttribute>();
                var isFirst = i++ == 0;

                var isPrimaryKey = propertyInfo.Name == OrmLiteConfig.IdField || (!hasIdField && isFirst)
                    || pkAttribute != null;

                var isNullableType = IsNullableType(propertyInfo.PropertyType);

                var isNullable = (!propertyInfo.PropertyType.IsValueType
                                   && propertyInfo.FirstAttribute<RequiredAttribute>() == null)
                                 || isNullableType;

                var propertyType = isNullableType
                    ? Nullable.GetUnderlyingType(propertyInfo.PropertyType)
                    : propertyInfo.PropertyType;

                var aliasAttr = propertyInfo.FirstAttribute<AliasAttribute>();

                var indexAttr = propertyInfo.FirstAttribute<IndexAttribute>();
                var isIndex = indexAttr != null;
                var isUnique = isIndex && indexAttr.Unique;

                var stringLengthAttr = propertyInfo.FirstAttribute<StringLengthAttribute>();

                var defaultValueAttr = propertyInfo.FirstAttribute<DefaultAttribute>();

                var referencesAttr = propertyInfo.FirstAttribute<ReferencesAttribute>();
                var foreignKeyAttr = propertyInfo.FirstAttribute<ForeignKeyAttribute>();

                if (decimalAttribute != null && stringLengthAttr == null)
                    stringLengthAttr = new StringLengthAttribute(decimalAttribute.Precision);

                var fieldDefinition = new FieldDefinition {
                    Name = propertyInfo.Name,
                    Alias = aliasAttr != null ? aliasAttr.Name : null,
                    FieldType = propertyType,
                    PropertyInfo = propertyInfo,
                    IsNullable = isNullable,
                    IsPrimaryKey = isPrimaryKey,
                    AutoIncrement =
                        isPrimaryKey &&
                        propertyInfo.FirstAttribute<AutoIncrementAttribute>() != null,
                    IsIndexed = isIndex,
                    IsUnique = isUnique,
                    FieldLength =
                        stringLengthAttr != null
                            ? stringLengthAttr.MaximumLength
                            : (int?)null,
                    DefaultValue =
                        defaultValueAttr != null ? defaultValueAttr.DefaultValue : null,
                    ForeignKey =
                        foreignKeyAttr == null
                            ? referencesAttr == null
                                  ? null
                                  : new ForeignKeyConstraint(referencesAttr.Type)
                            : new ForeignKeyConstraint(foreignKeyAttr.Type,
                                                       foreignKeyAttr.OnDelete,
                                                       foreignKeyAttr.OnUpdate,
                                                       foreignKeyAttr.ForeignKeyName),
                    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, 
                };

                if (propertyInfo.FirstAttribute<IgnoreAttribute>() != null)
                  modelDef.IgnoredFieldDefinitions.Add(fieldDefinition);
                else
                  modelDef.FieldDefinitions.Add(fieldDefinition);                
            }

            modelDef.SqlSelectAllFromTable = "SELECT {0} FROM {1} ".Fmt(OrmLiteConfig.DialectProvider.GetColumnNames(modelDef),
                                                                        OrmLiteConfig.DialectProvider.GetQuotedTableName(
                                                                            modelDef));
            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));

            return modelDef;
        }
 public static string GetQuotedColumnName(this IOrmLiteDialectProvider dialect, 
     FieldDefinition fieldDef)
 {
     return dialect.GetQuotedColumnName(fieldDef.FieldName);
 }
        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 IDbCommand SetParameters(this IDbCommand dbCmd, Type type, object anonType, bool excludeDefaults, ref string sql)
        {
            if (anonType == null)
            {
                return(dbCmd);
            }

            dbCmd.Parameters.Clear();

            var modelDef        = type.GetModelDefinition();
            var dialectProvider = dbCmd.GetDialectProvider();
            var fieldMap        = type.IsUserType() //Ensure T != Scalar<int>()
                ? dialectProvider.GetFieldDefinitionMap(modelDef)
                : null;

            var sqlCopy = sql; //C# doesn't allow changing ref params in lambda's

            var paramIndex = 0;

            anonType.ToObjectDictionary().ForEachParam(modelDef, excludeDefaults, (propName, columnName, value) =>
            {
                var propType = value?.GetType() ?? typeof(object);
                var inValues = GetMultiValues(value);
                if (inValues != null)
                {
                    var sb = StringBuilderCache.Allocate();
                    foreach (var item in inValues)
                    {
                        var p           = dbCmd.CreateParameter();
                        p.ParameterName = "v" + paramIndex++;

                        if (sb.Length > 0)
                        {
                            sb.Append(',');
                        }
                        sb.Append(dialectProvider.ParamString + p.ParameterName);

                        p.Direction = ParameterDirection.Input;
                        dialectProvider.InitDbParam(p, item.GetType());

                        dialectProvider.SetParamValue(p, item, item.GetType());

                        dbCmd.Parameters.Add(p);
                    }

                    var sqlIn = StringBuilderCache.ReturnAndFree(sb);
                    if (string.IsNullOrEmpty(sqlIn))
                    {
                        sqlIn = "NULL";
                    }
                    sqlCopy = sqlCopy?.Replace(dialectProvider.ParamString + propName, sqlIn);
                    if (dialectProvider.ParamString != "@")
                    {
                        sqlCopy = sqlCopy?.Replace("@" + propName, sqlIn);
                    }
                }
                else
                {
                    var p           = dbCmd.CreateParameter();
                    p.ParameterName = propName;
                    p.Direction     = ParameterDirection.Input;
                    dialectProvider.InitDbParam(p, propType);

                    FieldDefinition fieldDef = null;
                    fieldMap?.TryGetValue(columnName, out fieldDef);

                    dialectProvider.SetParamValue(p, value, propType, fieldDef);

                    dbCmd.Parameters.Add(p);
                }
            });

            sql = sqlCopy;
            return(dbCmd);
        }