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