public override DbExpression Visit(DbScanExpression expression)
        {
            var column = SoftDeleteAttribute.GetSoftDeleteColumnName(expression.Target.ElementType);

            if (column != null)
            {
                // Just because the entity has the soft delete annotation doesn't mean that
                // this particular table has the column. This occurs in situation like TPT
                // inheritance mapping and entity splitting where one type maps to multiple
                // tables.
                // We only apply the filter if the column is actually present in this table.
                // If not, then the query is going to be joining to the table that does have
                // the column anyway, so the filter will still be applied.
                var table = (EntityType)expression.Target.ElementType;
                if (table.Properties.Any(p => p.Name == column))
                {
                    var binding = DbExpressionBuilder.Bind(expression);
                    return(DbExpressionBuilder.Filter(
                               binding,
                               DbExpressionBuilder.NotEqual(
                                   DbExpressionBuilder.Property(
                                       DbExpressionBuilder.Variable(binding.VariableType, binding.VariableName),
                                       column),
                                   DbExpression.FromBoolean(true))));
                }
            }

            return(base.Visit(expression));
        }
Example #2
0
        async Task DoDelete(Entity entity, DeleteBehaviour behaviour)
        {
            // Raise deleting event
            if (!IsSet(behaviour, DeleteBehaviour.BypassDeleting))
            {
                var deletingArgs = new System.ComponentModel.CancelEventArgs();
                await Entity.Services.RaiseOnDeleting(entity, deletingArgs);

                if (deletingArgs.Cancel)
                {
                    Cache.Remove(entity);
                    return;
                }
            }

            if (SoftDeleteAttribute.IsEnabled(entity.GetType()) && !SoftDeleteAttribute.Context.ShouldByPassSoftDelete())
            {
                SoftDeleteAttribute.MarkDeleted(entity);
                await GetProvider(entity).Save(entity);
            }
            else
            {
                await GetProvider(entity).Delete(entity);
            }
        }
Example #3
0
        public async Task <IEnumerable <T> > GetSentEmails <T>() where T : IEmailMessage
        {
            using (new SoftDeleteAttribute.Context(bypassSoftdelete: false))
            {
                var records = await Database.GetList <T>();

                var result = records.OfType <Entity>().Where(x => SoftDeleteAttribute.IsMarked(x));
                return(result.Cast <T>());
            }
        }
        internal static DataProviderMetaData Generate(Type type)
        {
            var tableName = TableNameAttribute.GetTableName(type);

            return(new DataProviderMetaData(type)
            {
                BaseClassTypesInOrder = GetParents(type),
                DrivedClassTypes = GetDrivedClasses(type),
                Properties = GetProperties(type).ToArray(),
                Schema = SchemaAttribute.GetSchema(type),
                TableName = tableName,
                TableAlias = tableName,
                IsSoftDeleteEnabled = SoftDeleteAttribute.IsEnabled(type, inherit: false)
            });
        }
        public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
        {
            if (interceptionContext.OriginalResult.DataSpace != DataSpace.SSpace)
            {
                return;
            }

            if (interceptionContext.Result is DbQueryCommandTree queryCommand)
            {
                var newQuery = queryCommand.Query.Accept(new DeleteQueryVisitor());
                interceptionContext.Result = new DbQueryCommandTree(
                    queryCommand.MetadataWorkspace,
                    queryCommand.DataSpace,
                    newQuery);
            }

            if (!(interceptionContext.OriginalResult is DbDeleteCommandTree deleteCommand))
            {
                return;
            }

            var column = SoftDeleteAttribute.GetSoftDeleteColumnName(deleteCommand.Target.VariableType.EdmType);

            if (column == null)
            {
                return;
            }

            var setClauses = new List <DbModificationClause>();
            var table      = (EntityType)deleteCommand.Target.VariableType.EdmType;

            if (table.Properties.Any(p => p.Name == column))
            {
                setClauses.Add(DbExpressionBuilder.SetClause(
                                   deleteCommand.Target.VariableType.Variable(deleteCommand.Target.VariableName).Property(column),
                                   DbExpression.FromBoolean(true)));
            }

            var update = new DbUpdateCommandTree(
                deleteCommand.MetadataWorkspace,
                deleteCommand.DataSpace,
                deleteCommand.Target,
                deleteCommand.Predicate,
                setClauses.AsReadOnly(),
                null);

            interceptionContext.Result = update;
        }
Example #6
0
        public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
        {
            if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
            {
                var queryCommand = interceptionContext.Result as DbQueryCommandTree;
                if (queryCommand != null)
                {
                    var context = (DataContext)interceptionContext.DbContexts.Single(c => c is DataContext);

                    if (context.SoftDeleteFilterIsActive)
                    {
                        var newQuery = queryCommand.Query.Accept(new SoftDeleteQueryVisitor());
                        interceptionContext.Result = new DbQueryCommandTree(
                            queryCommand.MetadataWorkspace,
                            queryCommand.DataSpace,
                            newQuery);
                    }
                }

                var deleteCommand = interceptionContext.OriginalResult as DbDeleteCommandTree;
                if (deleteCommand != null)
                {
                    var column = SoftDeleteAttribute.GetSoftDeleteColumnName(deleteCommand.Target.VariableType.EdmType);
                    if (column != null)
                    {
                        var setClause =
                            DbExpressionBuilder.SetClause(
                                DbExpressionBuilder.Property(
                                    DbExpressionBuilder.Variable(deleteCommand.Target.VariableType, deleteCommand.Target.VariableName),
                                    column),
                                DbExpression.FromBoolean(true));

                        var update = new DbUpdateCommandTree(
                            deleteCommand.MetadataWorkspace,
                            deleteCommand.DataSpace,
                            deleteCommand.Target,
                            deleteCommand.Predicate,
                            new List <DbModificationClause> {
                            setClause
                        }.AsReadOnly(),
                            null);

                        interceptionContext.Result = update;
                    }
                }
            }
        }
Example #7
0
 IEntity HandleSoftDelete(Property[] fields, object[] values, IEntity entity)
 {
     if (ParticipatesInHierarchy)
     {
         var index = Array.FindIndex(fields, (x) => (x.Name == $"{ObjectType.TableName}__SoftDeleted"));
         if ((bool)values[index])
         {
             SoftDeleteAttribute.MarkDeleted((Entity)entity);
         }
     }
     else
     if ((bool)values[1])
     {
         SoftDeleteAttribute.MarkDeleted((Entity)entity);
     }
     return(entity);
 }
Example #8
0
        public virtual string GenerateWhere(IDatabaseQuery query)
        {
            var r = new StringBuilder();

            if (SoftDeleteAttribute.RequiresSoftdeleteQuery(query.EntityType))
            {
                query.Criteria.Add(new Criterion("IsMarkedSoftDeleted", false));
            }

            r.Append($" WHERE { query.Column("ID")} IS NOT NULL");

            foreach (var c in query.Criteria)
            {
                r.Append(Generate(query, c).WithPrefix(" AND "));
            }

            return(r.ToString());
        }
Example #9
0
        public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
        {
            if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
            {
                //This was Rowan Miller's example for filtering out IsDeleteds, but I'm going to try Jimmy Bogard's method instead.
                var queryCommand = interceptionContext.Result as DbQueryCommandTree;
                if (queryCommand != null)
                {
                    var newQuery = queryCommand.Query.Accept(new SoftDeleteQueryVisitor());
                    interceptionContext.Result = new DbQueryCommandTree(
                        queryCommand.MetadataWorkspace,
                        queryCommand.DataSpace,
                        newQuery);
                }

                var deleteCommand = interceptionContext.OriginalResult as DbDeleteCommandTree;
                if (deleteCommand != null)
                {
                    var column = SoftDeleteAttribute.GetSoftDeleteColumnName(deleteCommand.Target.VariableType.EdmType);
                    if (column != null)
                    {
                        var setClause =
                            DbExpressionBuilder.SetClause(
                                DbExpressionBuilder.Property(
                                    DbExpressionBuilder.Variable(deleteCommand.Target.VariableType, deleteCommand.Target.VariableName),
                                    column),
                                DbExpression.FromBoolean(true));

                        var update = new DbUpdateCommandTree(
                            deleteCommand.MetadataWorkspace,
                            deleteCommand.DataSpace,
                            deleteCommand.Target,
                            deleteCommand.Predicate,
                            new List <DbModificationClause> {
                            setClause
                        }.AsReadOnly(),
                            null);

                        interceptionContext.Result = update;
                    }
                }
            }
        }
Example #10
0
        public override string GenerateWhere(DatabaseQuery query)
        {
            var r = new StringBuilder();

            if (SoftDeleteAttribute.RequiresSoftdeleteQuery(query.EntityType))
            {
                query.Criteria.Add(new Criterion("IsMarkedSoftDeleted", false));
            }

            r.Append($" WHERE { MapColumn("ID")} IS NOT NULL");

            var whereGenerator = new SqlCriterionGenerator(query);

            foreach (var c in query.Criteria)
            {
                r.Append(whereGenerator.Generate(c).WithPrefix(" AND "));
            }

            return(r.ToString());
        }
        static IEnumerable <PropertyData> GetProperties(Type type)
        {
            var infos = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

            foreach (var(info, dbProp) in FilterProperties(infos))
            {
                yield return(GetUserDefinedPropertyData(info, dbProp));
            }

            if (infos.None(t => PrimaryKeyAttribute.IsPrimaryKey(t)))
            {
                yield return(GetDefaultIdPropertyData(type));
            }

            if (SoftDeleteAttribute.IsEnabled(type, inherit: false))
            {
                yield return(GetDeletedPropertyData(type));
            }

            yield return(GetOriginalIdPropertyData(type));
        }
        public override DbExpression Visit(DbScanExpression expression)
        {
            var column = SoftDeleteAttribute.GetSoftDeleteColumnName(expression.Target.ElementType);

            if (column == null)
            {
                return(base.Visit(expression));
            }

            var table = (EntityType)expression.Target.ElementType;

            if (table.Properties.All(p => p.Name != column))
            {
                return(base.Visit(expression));
            }

            var binding = expression.Bind();

            return(binding.Filter(binding.VariableType.Variable(binding.VariableName).Property(column)
                                  .NotEqual(DbExpression.FromBoolean(true))));
        }
        public override DbExpression Visit(DbScanExpression expression)
        {
            var column = SoftDeleteAttribute.GetSoftDeleteColumnName(expression.Target.ElementType);

            if (column != null)
            {
                var table = (EntityType)expression.Target.ElementType;
                if (table.Properties.Any(p => p.Name == column))
                {
                    var binding = DbExpressionBuilder.Bind(expression);
                    return(DbExpressionBuilder.Filter(
                               binding,
                               DbExpressionBuilder.NotEqual(
                                   DbExpressionBuilder.Property(
                                       DbExpressionBuilder.Variable(binding.VariableType, binding.VariableName),
                                       column),
                                   DbExpression.FromBoolean(true))));
                }
            }

            return(base.Visit(expression));
        }
        public override string GenerateWhere(DatabaseQuery query)
        {
            var r = new StringBuilder();

            if (SoftDeleteAttribute.RequiresSoftdeleteQuery(query.EntityType))
            {
                query.Criteria.Add(new Criterion("IsMarkedSoftDeleted", false));
            }

            r.Append($" WHERE { query.Column("Id")} IS NOT NULL");

            var whereGenerator = new PostgreSqlCriterionGenerator(query);
            var temp           = new List <ICriterion>();

            foreach (var c in query.Criteria)
            {
                if (c.PropertyName == "ID")
                {
                    temp.Add(c);
                }
            }

            query.Criteria.RemoveAll(x => x.PropertyName == "ID");

            foreach (var c in temp)
            {
                query.Criteria.Add(new Criterion("Id", c.FilterFunction, c.Value));
            }

            foreach (var c in query.Criteria)
            {
                r.Append(whereGenerator.Generate(c).WithPrefix(" AND "));
            }

            return(r.ToString());
        }
Example #15
0
 /// <summary>
 /// Constructor for fields using information obtained from the TableColumn attribute.
 /// </summary>
 public FieldMap(ObjectMap map, MemberAttributeInfo memberAttributeInfo)
 {
     this.map   = map;
     memberInfo = memberAttributeInfo.MemberInfo;
     if (memberInfo is PropertyInfo)
     {
         memberType = (memberInfo as PropertyInfo).PropertyType;
     }
     else
     {
         memberType = (memberInfo as FieldInfo).FieldType;
     }
     // extract information from attributes
     if (memberAttributeInfo.Attributes != null)
     {
         foreach (Attribute attr in memberAttributeInfo.Attributes)
         {
             if (attr is TableColumnAttribute)
             {
                 TableColumnAttribute tc = attr as TableColumnAttribute;
                 SetColumnName(tc.Name ?? memberInfo.Name);
                 SetNullValue(tc.NullValue);
                 SetIsNullable(!tc.NotNull);
                 SetSize(tc.Size);
                 if (tc.HasDbType)
                 {
                     SetDbType(tc.DatabaseType);
                 }
                 else
                 {
                     SetDbType(NO_DBTYPE);
                 }
                 handleEnumAsString = tc.HandleEnumAsString;
                 isReadOnly         = tc.IsReadOnly;
                 isUpdateAfterWrite = tc.IsUpdateAfterWrite;
             }
             else if (attr is PrimaryKeyAttribute)
             {
                 PrimaryKeyAttribute pk = attr as PrimaryKeyAttribute;
                 SetIsPrimaryKey(true);
                 SetIsAutoGenerated(pk.AutoGenerated);
                 if (IsAutoGenerated)
                 {
                     map.IdentityMap = this;
                 }
             }
             else if (attr is ForeignKeyAttribute)
             {
                 ForeignKeyAttribute fk = attr as ForeignKeyAttribute;
                 SetForeignKeyTableName(fk.ForeignTable);
                 SetForeignKeyColumnName(fk.ForeignColumn);
             }
             else if (attr is ConcurrencyAttribute)
             {
                 ConcurrencyAttribute ca = attr as ConcurrencyAttribute;
                 Check.Verify(memberType == typeof(int) || memberType == typeof(long),
                              Error.DeveloperError, "Unsupported property type {0} for ConcurrencyAttribute {1}",
                              memberInfo.ReflectedType, memberInfo.Name);
                 isConcurrencyColumn = true;
                 map.ConcurrencyMap  = this;
             }
             else if (attr is SoftDeleteAttribute)
             {
                 SoftDeleteAttribute sd = attr as SoftDeleteAttribute;
                 Check.Verify(memberType == typeof(int) || memberType == typeof(long),
                              Error.DeveloperError, "Unsupported property type {0} for SoftDeleteAttribute {1}",
                              memberInfo.ReflectedType, memberInfo.Name);
                 isSoftDeleteColumn = true;
                 map.SoftDeleteMap  = this;
             }
             else if (attr is SequenceNameAttribute)
             {
                 // sequence name used when available (in place of name conventions or autodetected value)
                 sequenceName = (attr as SequenceNameAttribute).Name;
             }
             else if (attr is InheritanceAttribute)
             {
                 // sequence name used when available (in place of name conventions or autodetected value)
                 map.InheritanceMap = this;
             }
         }
     }
 }
        /// <summary>
        /// Loads the property map.
        /// </summary>
        /// <param name="propertyInfo">The proerty info.</param>
        /// <returns>The property map for this property.</returns>
        /// <exception cref="ArgumentException">Readonly and Editable attributes specified with opposing values.</exception>
        public static PropertyMap LoadPropertyMap(PropertyInfo propertyInfo)
        {
            // if the property info is null or not mapped attribute present
            // then return null
            if (propertyInfo == null || propertyInfo.GetCustomAttribute <NotMappedAttribute>() != null)
            {
                return(null);
            }

            PropertyMap pm = new PropertyMap()
            {
                PropertyInfo = propertyInfo
            };

            // read custom attributes from property info
            KeyAttribute        key                 = propertyInfo.GetCustomAttribute(typeof(KeyAttribute)) as KeyAttribute;
            KeyTypeAttribute    keyType             = propertyInfo.GetCustomAttribute(typeof(KeyTypeAttribute)) as KeyTypeAttribute;
            ColumnAttribute     column              = propertyInfo.GetCustomAttribute(typeof(ColumnAttribute)) as ColumnAttribute;
            ReadOnlyAttribute   readOnly            = propertyInfo.GetCustomAttribute(typeof(ReadOnlyAttribute)) as ReadOnlyAttribute;
            EditableAttribute   editable            = propertyInfo.GetCustomAttribute(typeof(EditableAttribute)) as EditableAttribute;
            RequiredAttribute   required            = propertyInfo.GetCustomAttribute(typeof(RequiredAttribute)) as RequiredAttribute;
            DateStampAttribute  dateStamp           = propertyInfo.GetCustomAttribute(typeof(DateStampAttribute)) as DateStampAttribute;
            SoftDeleteAttribute softDeleteAttribute = propertyInfo.GetCustomAttribute(typeof(SoftDeleteAttribute)) as SoftDeleteAttribute;

            // check whether this property is an implied key
            bool impliedKey = propertyInfo.Name == "Id" || $"{propertyInfo.DeclaringType.Name}Id" == propertyInfo.Name;
            bool isKey      = impliedKey || key != null || keyType != null;

            // is this an implied or explicit key then set the key type
            if (isKey)
            {
                // if key type not provided then imply key type
                if (keyType == null)
                {
                    if (propertyInfo.PropertyType == typeof(int))
                    {
                        // if integer then treat as identity by default
                        pm.KeyType = KeyType.Identity;
                    }
                    else if (propertyInfo.PropertyType == typeof(Guid))
                    {
                        // if guid then treat as guid
                        pm.KeyType = KeyType.Guid;
                    }
                    else
                    {
                        // otherwise treat as assigned
                        pm.KeyType = KeyType.Assigned;
                    }
                }
                else
                {
                    pm.KeyType = keyType.KeyType;
                }
            }

            // set remaining properties
            pm.Column        = column != null ? column.Name : propertyInfo.Name;
            pm.IsRequired    = required != null ? true : false;
            pm.IsDateStamp   = dateStamp != null ? true : false;
            pm.InsertedValue = softDeleteAttribute?.ValueOnInsert;
            pm.DeleteValue   = softDeleteAttribute?.ValueOnDelete;
            pm.IsSoftDelete  = softDeleteAttribute != null;

            // set read-only / editable
            // if property is identity, guid or sequential key then cannot be
            // editable and must be read-only
            if (pm.KeyType == KeyType.Identity || pm.KeyType == KeyType.Guid || pm.KeyType == KeyType.Sequential)
            {
                pm.IsReadOnly = true;
                pm.IsEditable = false;
            }
            else
            {
                // otherwise obey the attributes
                pm.IsReadOnly = readOnly != null ? readOnly.IsReadOnly : false;

                if (pm.IsReadOnly && editable == null)
                {
                    pm.IsEditable = false;
                }
                else
                {
                    pm.IsEditable = editable != null ? editable.AllowEdit : true;
                }
            }

            // if editable and readonly conflict throw an error
            if (pm.IsEditable && pm.IsReadOnly)
            {
                throw new ArgumentException("Readonly and Editable attributes specified with opposing values");
            }

            return(pm);
        }