示例#1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SqlTypeInfo"/> class.
        /// </summary>
        /// <param name="type">The table type.</param>
        /// <param name="adapter">The adapter used to generate SQL commands.</param>
        public SqlTypeInfo(Type type, ISqlAdapter adapter)
        {
            Type    = type;
            Adapter = adapter ?? SqlAdapter.GetAdapter(ExtraCrud.Dialect);
            TableAttribute tableAttr = type.GetCustomAttribute <TableAttribute>(false);
            BindingFlags   flags     = BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.NonPublic;

            // Determine the TableName, Adapter, and BindingFlags
            bool inherit = false;

            if (tableAttr == null)
            {
                var tableAttr2 = type.GetCustomAttribute <System.ComponentModel.DataAnnotations.Schema.TableAttribute>(false);
                if (tableAttr2 != null && !string.IsNullOrWhiteSpace(tableAttr2.Schema))
                {
                    TableName = tableAttr2.Name;
                    if (!string.IsNullOrWhiteSpace(tableAttr2.Schema))
                    {
                        Schema = tableAttr2.Schema.Trim();
                    }
                }
                else
                {
                    TableName = type.Name;
                }
            }
            else
            {
                TableName = string.IsNullOrWhiteSpace(tableAttr.Name) ? type.Name : tableAttr.Name;
                if (tableAttr.DeclaredOnly)
                {
                    flags      |= BindingFlags.DeclaredOnly;
                    Attributes |= SqlTableAttributes.DeclaredOnly;
                }
                if (tableAttr.InheritAttributes)
                {
                    inherit     = true;
                    Attributes |= SqlTableAttributes.InheritAttributes;
                }
                if (!string.IsNullOrWhiteSpace(tableAttr.Schema))
                {
                    Schema = tableAttr.Schema.Trim();
                }
            }
            FullyQualifiedTableName = TableName;
            if (Schema != null)
            {
                FullyQualifiedTableName = Schema + "." + TableName;
            }

            // Filter properties and iterate them for primary keys
            PropertyInfo[] properties      = type.GetProperties(flags);
            PropertyInfo[] validProperties = properties.Where(ExtraCrud.IsValidProperty).Where(prop => {
                return(prop.GetCustomAttribute <NotMappedAttribute>(inherit) == null &&
                       prop.GetCustomAttribute <System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute>(inherit) == null);
            }).ToArray();
            if (!validProperties.Any())
            {
                throw new InvalidOperationException(type.FullName + " does not have any valid properties.");
            }
            ReadOnlyAttribute readOnlyAttr = type.GetCustomAttribute <ReadOnlyAttribute>(false);

            if (readOnlyAttr != null)
            {
                Attributes |= SqlTableAttributes.IgnoreInsert | SqlTableAttributes.IgnoreUpdate | SqlTableAttributes.IgnoreDelete;
            }
            else
            {
                var editableAttr = type.GetCustomAttribute <System.ComponentModel.DataAnnotations.EditableAttribute>(false);
                AutoSyncAttribute autoSyncAttr = type.GetCustomAttribute <AutoSyncAttribute>(false);
                if (autoSyncAttr != null)
                {
                    if (autoSyncAttr.SyncUpdate)
                    {
                        Attributes |= SqlTableAttributes.UpdateAutoSync;
                    }
                    if (autoSyncAttr.SyncInsert)
                    {
                        Attributes |= SqlTableAttributes.InsertAutoSync;
                    }
                }
                if (editableAttr != null)
                {
                    if (!editableAttr.AllowEdit)
                    {
                        Attributes |= SqlTableAttributes.IgnoreUpdate;
                    }
                    if (editableAttr.AllowInitialValue)
                    {
                        Attributes |= SqlTableAttributes.IgnoreInsert;
                    }
                }
                else
                {
                    IgnoreInsertAttribute noInserts = type.GetCustomAttribute <IgnoreInsertAttribute>(false);
                    if (noInserts != null)
                    {
                        Attributes |= SqlTableAttributes.IgnoreInsert;
                    }
                    IgnoreUpdateAttribute noUpdates = type.GetCustomAttribute <IgnoreUpdateAttribute>(false);
                    if (noUpdates != null)
                    {
                        Attributes |= SqlTableAttributes.IgnoreUpdate;
                    }
                }
                IgnoreDeleteAttribute noDeletes = type.GetCustomAttribute <IgnoreDeleteAttribute>(false);
                if (noDeletes != null)
                {
                    Attributes |= SqlTableAttributes.IgnoreDelete;
                }
            }

            // Determine primary key
            List <SqlColumn> keys    = new List <SqlColumn>();
            List <SqlColumn> columns = new List <SqlColumn>();
            int autoKeyCount         = 0;

            for (int i = 0; i < validProperties.Length; i++)
            {
                PropertyInfo    prop       = validProperties[i];
                string          columnName = null;
                ColumnAttribute columnAttr = prop.GetCustomAttribute <ColumnAttribute>(inherit);
                if (columnAttr != null)
                {
                    columnName = columnAttr.Name;
                }
                else
                {
                    var columnAttr2 = prop.GetCustomAttribute <System.ComponentModel.DataAnnotations.Schema.ColumnAttribute>(inherit);
                    if (columnAttr2 != null)
                    {
                        columnName = columnAttr2.Name;
                    }
                }
                string       propName = Adapter.QuoteIdentifier(prop.Name);
                SqlColumn    column   = new SqlColumn(prop, string.IsNullOrWhiteSpace(columnName) ? propName : Adapter.QuoteIdentifier(columnName), propName, i);
                KeyAttribute keyAttr  = prop.GetCustomAttribute <KeyAttribute>(inherit);
                if (keyAttr != null)
                {
                    if (keyAttr.AutoIncrement)
                    {
                        autoKeyCount++;
                    }
                    column.Attributes = keyAttr.AutoIncrement ? SqlColumnAttributes.AutoKey : SqlColumnAttributes.Key;
                }
                else
                {
                    var keyAttrCm = prop.GetCustomAttribute <System.ComponentModel.DataAnnotations.KeyAttribute>(inherit);
                    if (keyAttrCm != null)
                    {
                        var requiredAttr = prop.GetCustomAttribute <System.ComponentModel.DataAnnotations.RequiredAttribute>(inherit);
                        if (requiredAttr != null && ExtraCrud.IsValidAutoIncrementType(prop.PropertyType))
                        {
                            column.Attributes |= SqlColumnAttributes.Key;
                        }
                        else
                        {
                            column.Attributes |= SqlColumnAttributes.AutoKey;
                            autoKeyCount++;
                        }
                    }
                }
                if (column.IsKey)
                {
                    keys.Add(column);
                    if (!prop.CanRead || !prop.GetMethod.IsPublic || prop.GetMethod.IsStatic)
                    {
                        Attributes |= SqlTableAttributes.IgnoreInsert | SqlTableAttributes.IgnoreUpdate | SqlTableAttributes.IgnoreDelete;
                    }
                }
                columns.Add(column);
            }
            if (keys.Count == 0)
            {
                string    quotedId = Adapter.QuoteIdentifier("ID");
                SqlColumn key      = columns.FirstOrDefault(c => string.Equals(c.ColumnName, quotedId, StringComparison.OrdinalIgnoreCase));
                if (key == null)
                {
                    quotedId = Adapter.QuoteIdentifier(type.Name + "ID");
                    key      = columns.Where(c => c.ColumnName.Equals(quotedId, StringComparison.OrdinalIgnoreCase)).OrderByDescending(c => c.ColumnName.Contains(type.Name)).FirstOrDefault();
                }
                if (key != null)
                {
                    var requiredAttr = key.Property.GetCustomAttribute <System.ComponentModel.DataAnnotations.RequiredAttribute>(inherit);
                    if (requiredAttr == null)
                    {
                        key.Attributes |= SqlColumnAttributes.AutoKey;
                    }
                    else
                    {
                        key.Attributes |= SqlColumnAttributes.Key;
                    }
                    keys.Add(key);
                }
                else
                {
                    KeyColumns = Constants.SqlColumnsEmpty;
                }
            }
            if (keys.Count != 0)
            {
                KeyColumns = keys.ToArray();
                if (KeyColumns.Count == 1 && KeyColumns[0].IsAutoKey && ExtraCrud.IsValidAutoIncrementType(KeyColumns[0].Type))
                {
                    AutoKeyColumn = KeyColumns[0];
                }
                else if (autoKeyCount != 0 && KeyColumns.Count != autoKeyCount)
                {
                    throw new InvalidOperationException(Type.FullName + " cannot have a both a composite key and an autoincrement key.");
                }
                else
                {
                    // remove SqlColumnAttributes.AutoKey from all key columns
                    SqlColumnAttributes invertedAutoKey = ~(SqlColumnAttributes.AutoKey ^ SqlColumnAttributes.Key);
                    foreach (SqlColumn key in KeyColumns)
                    {
                        key.Attributes &= invertedAutoKey;
                    }
                }
            }

            foreach (SqlColumn column in columns.Where(c => !c.IsKey))
            {
                PropertyInfo prop = column.Property;

                bool selectOnly = !prop.CanRead || !prop.GetMethod.IsPublic || prop.GetMethod.IsStatic;
                if (selectOnly)
                {
                    column.Attributes |= SqlColumnAttributes.IgnoreInsert | SqlColumnAttributes.IgnoreUpdate | SqlColumnAttributes.IgnoreDelete;
                }

                // Selects
                IgnoreSelectAttribute selectAttr = prop.GetCustomAttribute <IgnoreSelectAttribute>(inherit);
                if (selectAttr != null)
                {
                    column.Attributes |= SqlColumnAttributes.IgnoreSelect;
                    if (selectOnly)
                    {
                        continue;
                    }
                }
                else if (selectOnly)
                {
                    continue;
                }
                else
                {
                    AutoSyncAttribute autoSyncAttr = prop.GetCustomAttribute <AutoSyncAttribute>(inherit);
                    if (autoSyncAttr != null)
                    {
                        if (autoSyncAttr.SyncInsert)
                        {
                            column.Attributes |= SqlColumnAttributes.InsertAutoSync;
                        }
                        if (autoSyncAttr.SyncUpdate)
                        {
                            column.Attributes |= SqlColumnAttributes.UpdateAutoSync;
                        }
                    }
                    if (InsertAutoSync)
                    {
                        column.Attributes |= SqlColumnAttributes.InsertAutoSync;
                    }
                    if (UpdateAutoSync)
                    {
                        column.Attributes |= SqlColumnAttributes.UpdateAutoSync;
                    }
                }

                // Deletes
                MatchDeleteAttribute deleteAttr = prop.GetCustomAttribute <MatchDeleteAttribute>(inherit);
                if (deleteAttr != null || IgnoreDelete)
                {
                    column.Attributes |= SqlColumnAttributes.IgnoreDelete;
                }

                readOnlyAttr = prop.GetCustomAttribute <ReadOnlyAttribute>(inherit);
                if (readOnlyAttr != null)
                {
                    column.Attributes |= SqlColumnAttributes.IgnoreInsert | SqlColumnAttributes.IgnoreUpdate;
                    continue;
                }
                var editableAttr = prop.GetCustomAttribute <System.ComponentModel.DataAnnotations.EditableAttribute>(inherit);
                if (editableAttr != null)
                {
                    if (!editableAttr.AllowInitialValue)
                    {
                        column.Attributes |= SqlColumnAttributes.IgnoreUpdate;
                    }
                    if (!editableAttr.AllowEdit)
                    {
                        column.Attributes |= SqlColumnAttributes.IgnoreUpdate;
                    }
                }

                // Inserts
                IgnoreInsertAttribute insertAttr = prop.GetCustomAttribute <IgnoreInsertAttribute>(inherit);
                if (insertAttr != null)
                {
                    column.Attributes |= SqlColumnAttributes.IgnoreInsert;
                    column.InsertValue = insertAttr.Value;
                    if (insertAttr.AutoSync)
                    {
                        column.Attributes |= SqlColumnAttributes.InsertAutoSync;
                    }
                }
                else if (IgnoreInsert)
                {
                    column.Attributes |= SqlColumnAttributes.IgnoreInsert;
                }

                // Updates
                IgnoreUpdateAttribute ignoreUpdateAttr = prop.GetCustomAttribute <IgnoreUpdateAttribute>(inherit);
                if (ignoreUpdateAttr != null)
                {
                    column.Attributes |= SqlColumnAttributes.IgnoreUpdate;
                    column.UpdateValue = ignoreUpdateAttr.Value;
                    if (ignoreUpdateAttr.AutoSync)
                    {
                        column.Attributes |= SqlColumnAttributes.UpdateAutoSync;
                    }
                }
                else if (IgnoreUpdate)
                {
                    column.Attributes = SqlColumnAttributes.IgnoreUpdate;
                }
                else
                {
                    MatchUpdateAttribute matchUpdateAttr = prop.GetCustomAttribute <MatchUpdateAttribute>(inherit);                    //NOTE: MatchUpdate != IgnoreUpdate
                    if (matchUpdateAttr != null)
                    {
                        column.Attributes |= SqlColumnAttributes.MatchUpdate;
                        column.UpdateValue = matchUpdateAttr.Value;
                        if (matchUpdateAttr.AutoSync)
                        {
                            column.Attributes |= SqlColumnAttributes.UpdateAutoSync;
                        }
                    }
                }
            }
            if (columns.Count == 0)
            {
                throw new InvalidOperationException(type.FullName + " does not have any valid properties.");                 // double check
            }
            Columns          = columns.ToArray();
            EqualityColumns  = KeyColumns.Count == 0 || KeyColumns.Count == Columns.Count ? Columns : KeyColumns;
            UpdateKeyColumns = Columns == EqualityColumns ? Constants.SqlColumnsEmpty : Columns.Where(c => c.IsKey || c.MatchUpdate).ToArray();
            DeleteKeyColumns = Columns == EqualityColumns ? Columns : Columns.Where(c => c.IsKey || c.MatchDelete).ToArray();
        }
示例#2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SqlTypeInfo"/> class.
 /// </summary>
 /// <param name="type">The table type.</param>
 /// <param name="dialect">The dialect used to generate SQL commands.</param>
 public SqlTypeInfo(Type type, SqlDialect dialect = SqlDialect.SQLServer)
     : this(type, SqlAdapter.GetAdapter(dialect))
 {
 }