/// <summary>
        /// Retrieves an attribute that applies to a specific dialect.
        /// </summary>
        /// <typeparam name="T">The attribute to retrieve.</typeparam>
        /// <param name="dialect">A dialect that the attribute should apply to.</param>
        /// <param name="property">The property that the attribute is applied to.</param>
        /// <returns>An attribute for the given property. This will be <c>null</c> when no attribute is present.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="dialect"/> or <paramref name="property"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">More than one matching attribute was found.</exception>
        public static T GetDialectAttribute <T>(this IDatabaseDialect dialect, PropertyInfo property) where T : ModelledSchemaAttribute
        {
            if (dialect == null)
            {
                throw new ArgumentNullException(nameof(dialect));
            }
            if (property == null)
            {
                throw new ArgumentNullException(nameof(property));
            }

            var dialectType = dialect.GetType();
            var attrs       = property.GetCustomAttributes <T>(true)
                              .Where(attr => attr.SupportsDialect(dialectType))
                              .ToList();

            if (attrs.Count > 1)
            {
                throw new ArgumentException($"More than one matching { typeof(T).FullName } attribute was found for the property { property.Name } in { property.ReflectedType.FullName }.", nameof(property));
            }

            return(attrs.SingleOrDefault());
        }
Example #2
0
        public ReflectionColumnDataType(IDatabaseDialect dialect, Type columnType, Type clrType)
        {
            if (dialect == null)
            {
                throw new ArgumentNullException(nameof(dialect));
            }
            if (columnType == null)
            {
                throw new ArgumentNullException(nameof(columnType));
            }
            if (clrType == null)
            {
                throw new ArgumentNullException(nameof(clrType));
            }

            var attr = dialect.GetDialectAttribute <DeclaredTypeAttribute>(columnType);

            if (attr == null)
            {
                throw new ArgumentException($"The column type { columnType.FullName } does not contain a definition for the dialect { dialect.GetType().FullName }");
            }

            var typeProvider = dialect.TypeProvider;

            if (typeProvider == null)
            {
                throw new ArgumentException("The given dialect does not contain a valid type provider.", nameof(dialect));
            }

            var collationAttr = dialect.GetDialectAttribute <CollationAttribute>(columnType);
            var typeMetadata  = new ColumnTypeMetadata
            {
                ClrType   = clrType,
                Collation = collationAttr?.CollationName != null
                    ? Option <Identifier> .Some(collationAttr.CollationName)
                    : Option <Identifier> .None,
                DataType         = attr.DataType,
                IsFixedLength    = attr.IsFixedLength,
                MaxLength        = attr.Length,
                NumericPrecision = attr.Precision > 0 && attr.Scale > 0
                    ? Option <INumericPrecision> .Some(new NumericPrecision(attr.Precision, attr.Scale))
                    : Option <INumericPrecision> .None,
            };
            var dbType = typeProvider.CreateColumnType(typeMetadata);

            // map dbType to properties, avoids keeping a reference
            TypeName         = dbType.TypeName;
            DataType         = dbType.DataType;
            Definition       = dbType.Definition;
            IsFixedLength    = dbType.IsFixedLength;
            MaxLength        = dbType.MaxLength;
            ClrType          = dbType.ClrType;
            NumericPrecision = dbType.NumericPrecision;
            Collation        = dbType.Collation;
        }