Forked from marisks/CreatedAndModifiedDateInterceptor.cs
Created
April 14, 2016 03:01
-
-
Save ivan-marquez/d12c3c6881a5d361ba842f72a917bf0f to your computer and use it in GitHub Desktop.
Entity Framework soft delete, modiefied and created date interceptors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Data.Entity.Core.Common.CommandTrees; | |
using System.Data.Entity.Core.Metadata.Edm; | |
using System.Data.Entity.Infrastructure.Interception; | |
using System.Linq; | |
public class CreatedAndModifiedDateInterceptor : IDbCommandTreeInterceptor | |
{ | |
public const string CreatedColumnName = "Created"; | |
public const string ModifiedColumnName = "Modified"; | |
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext) | |
{ | |
if (interceptionContext.OriginalResult.DataSpace != DataSpace.SSpace) | |
{ | |
return; | |
} | |
var insertCommand = interceptionContext.Result as DbInsertCommandTree; | |
if (insertCommand != null) | |
{ | |
interceptionContext.Result = HandleInsertCommand(insertCommand); | |
} | |
var updateCommand = interceptionContext.OriginalResult as DbUpdateCommandTree; | |
if (updateCommand != null) | |
{ | |
interceptionContext.Result = HandleUpdateCommand(updateCommand); | |
} | |
} | |
private static DbCommandTree HandleInsertCommand(DbInsertCommandTree insertCommand) | |
{ | |
var now = DateTime.Now; | |
var setClauses = insertCommand.SetClauses | |
.Select(clause => clause.UpdateIfMatch(CreatedColumnName, DbExpression.FromDateTime(now))) | |
.Select(clause => clause.UpdateIfMatch(ModifiedColumnName, DbExpression.FromDateTime(now))) | |
.ToList(); | |
return new DbInsertCommandTree( | |
insertCommand.MetadataWorkspace, | |
insertCommand.DataSpace, | |
insertCommand.Target, | |
setClauses.AsReadOnly(), | |
insertCommand.Returning); | |
} | |
private static DbCommandTree HandleUpdateCommand(DbUpdateCommandTree updateCommand) | |
{ | |
var now = DateTime.Now; | |
var setClauses = updateCommand.SetClauses | |
.Select(clause => clause.UpdateIfMatch(ModifiedColumnName, DbExpression.FromDateTime(now))) | |
.ToList(); | |
return new DbUpdateCommandTree( | |
updateCommand.MetadataWorkspace, | |
updateCommand.DataSpace, | |
updateCommand.Target, | |
updateCommand.Predicate, | |
setClauses.AsReadOnly(), null); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Data.Entity; | |
public class EntityFrameworkConfiguration : DbConfiguration | |
{ | |
public EntityFrameworkConfiguration() | |
{ | |
AddInterceptor(new SoftDeleteInterceptor()); | |
AddInterceptor(new CreatedAndModifiedDateInterceptor()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Data.Entity.Core.Common.CommandTrees; | |
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder; | |
public static class Extensions | |
{ | |
public static DbModificationClause UpdateIfMatch( | |
this DbModificationClause clause, | |
string property, | |
DbExpression value) | |
{ | |
return clause.IsFor(property) | |
? DbExpressionBuilder.SetClause(clause.Property(), value) | |
: clause; | |
} | |
public static bool IsFor( | |
this DbModificationClause clause, | |
string property) | |
{ | |
return clause.HasPropertyExpression() | |
&& clause.Property().Property.Name == property; | |
} | |
public static DbPropertyExpression Property( | |
this DbModificationClause clause) | |
{ | |
if (clause.HasPropertyExpression()) | |
{ | |
var setClause = (DbSetClause) clause; | |
return (DbPropertyExpression) setClause.Property; | |
} | |
var message = | |
"clause does not contain property expression. " + | |
"Use HasPropertyExpression method to check if it has property expression."; | |
throw new Exception(message); | |
} | |
public static bool HasPropertyExpression( | |
this DbModificationClause modificationClause) | |
{ | |
var setClause = modificationClause as DbSetClause; | |
return setClause?.Property is DbPropertyExpression; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Data.Entity.Core.Common.CommandTrees; | |
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder; | |
using System.Data.Entity.Core.Metadata.Edm; | |
using System.Data.Entity.Infrastructure.Interception; | |
using System.Linq; | |
public class SoftDeleteInterceptor : IDbCommandTreeInterceptor | |
{ | |
public const string IsDeletedColumnName = "IsDeleted"; | |
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext) | |
{ | |
if (interceptionContext.OriginalResult.DataSpace != DataSpace.SSpace) | |
{ | |
return; | |
} | |
var queryCommand = interceptionContext.Result as DbQueryCommandTree; | |
if (queryCommand != null) | |
{ | |
interceptionContext.Result = HandleQueryCommand(queryCommand); | |
} | |
var deleteCommand = interceptionContext.OriginalResult as DbDeleteCommandTree; | |
if (deleteCommand != null) | |
{ | |
interceptionContext.Result = HandleDeleteCommand(deleteCommand); | |
} | |
} | |
private static DbCommandTree HandleQueryCommand(DbQueryCommandTree queryCommand) | |
{ | |
var newQuery = queryCommand.Query.Accept(new SoftDeleteQueryVisitor()); | |
return new DbQueryCommandTree( | |
queryCommand.MetadataWorkspace, | |
queryCommand.DataSpace, | |
newQuery); | |
} | |
private static DbCommandTree HandleDeleteCommand(DbDeleteCommandTree deleteCommand) | |
{ | |
var setClauses = new List<DbModificationClause>(); | |
var table = (EntityType) deleteCommand.Target.VariableType.EdmType; | |
if (table.Properties.All(p => p.Name != IsDeletedColumnName)) | |
{ | |
return deleteCommand; | |
} | |
setClauses.Add(DbExpressionBuilder.SetClause( | |
deleteCommand.Target.VariableType.Variable(deleteCommand.Target.VariableName).Property(IsDeletedColumnName), | |
DbExpression.FromBoolean(true))); | |
return new DbUpdateCommandTree( | |
deleteCommand.MetadataWorkspace, | |
deleteCommand.DataSpace, | |
deleteCommand.Target, | |
deleteCommand.Predicate, | |
setClauses.AsReadOnly(), null); | |
} | |
public class SoftDeleteQueryVisitor : DefaultExpressionVisitor | |
{ | |
public override DbExpression Visit(DbScanExpression expression) | |
{ | |
var table = (EntityType)expression.Target.ElementType; | |
if (table.Properties.All(p => p.Name != IsDeletedColumnName)) | |
{ | |
return base.Visit(expression); | |
} | |
var binding = expression.Bind(); | |
return binding.Filter( | |
binding.VariableType | |
.Variable(binding.VariableName) | |
.Property(IsDeletedColumnName) | |
.NotEqual(DbExpression.FromBoolean(true))); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment