Entity Framework 使用数据库拦截器的软删除实现不起作用
Entity Framework soft delete implementation using database interceptor not working
我使用以下教程实现了数据库软删除(将条目标记为已删除的布尔标志):http://www.codeguru.com/csharp/csharp/soft-deleting-entities-cleanly-using-entity-framework-6-interceptors.html
在我看来,这是一个非常好的实现,因为一旦设置好软删除,只需添加一个 [SoftDelete("IsDeleted")]
注释即可将其应用于模型。问题是到目前为止它还没有工作。
来源似乎是可靠的,他们甚至发布了他们解决方案的示例:https://github.com/rakeshbabuparuchuri/EFExpensionPoints
如果我在对我的项目应用软删除时做错了什么,你能看看我的代码吗?
这是模特:
[SoftDelete("IsDeleted")]
public class BC_Instance
{
public int ID { get; set; }
public bool IsDeleted { get; set; }
}
ApplicationDbContext.cs:
namespace bcplatform2.Models
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
// Add a DbSet for each one of your Entities
//public DbSet<VirtualGuest> VirtualGuests { get; set; }
public DbSet<BC_Instance> BiocloudInstances { get; set; }
static ApplicationDbContext()
{
Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected new void OnModelCreating(DbModelBuilder modelBuilder)
{
var conv = new AttributeToTableAnnotationConvention<SoftDeleteAttribute, string>(
"SoftDeleteColumnName",
(type, attributes) => attributes.Single().ColumnName);
modelBuilder.Conventions.Add(conv);
}
}
}
ApplicationDbConfiguration.cs
namespace bcplatform2.DAL
{
public class ApplicationDbConfiguration : DbConfiguration
{
public ApplicationDbConfiguration()
{
AddInterceptor(new SoftDeleteInterceptor());
}
}
}
SoftDeleteAttribute.cs:
namespace bcplatform2.Helpers
{
public class SoftDeleteAttribute : Attribute
{
public SoftDeleteAttribute(string column)
{
ColumnName = column;
}
public string ColumnName { get; set; }
public static string GetSoftDeleteColumnName(EdmType type)
{
MetadataProperty annotation = type.MetadataProperties
.Where(p => p.Name.EndsWith("customannotation:SoftDeleteColumnName"))
.SingleOrDefault();
return annotation == null ? null : (string)annotation.Value;
}
}
}
SoftDeleteInterceptor.cs
我注意到SoftDeleteAttribute.GetSoftDeleteColumnName(deleteCommand.Target.VariableType.EdmType)
没有找到软删除属性,returns为空。但是不知道为什么。
namespace bcplatform2.Helpers
{
public class SoftDeleteInterceptor : IDbCommandTreeInterceptor
{
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
{
if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
{
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 setClauses = new List<DbModificationClause>();
var table = (EntityType)deleteCommand.Target.VariableType.EdmType;
if (table.Properties.Any(p => p.Name == column))
{
setClauses.Add(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,
setClauses.AsReadOnly(),
null);
interceptionContext.Result = update;
}
}
}
}
}
}
IdentityConfig.cs
public class ApplicationDbInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
InitializeIdentityForEF(context);
base.Seed(context);
}
//Create User=Admin@Admin.com with password=Admin@123456 in the Admin role
public static void InitializeIdentityForEF(ApplicationDbContext db)
{
//Initialize users and roles...
}
}
好吧,我觉得你的代码不错。也许有一个小错误正在破坏您的应用程序。你可以试试这个:
从 BC_Instance
中删除 SoftDeleteAttribute
编辑OnModelCreating
方法
AttributeToTableAnnotationConvention<SoftDeleteAttribute, string> conv =
new AttributeToTableAnnotationConvention<SoftDeleteAttribute, string>(
"SoftDeleteColumnName",
(type, attributes) => attributes.Single().ColumnName);
modelBuilder.Conventions.Add(conv);
//this will dynamically add the attribute to all models
modelBuilder.Types().Configure(delegate(ConventionTypeConfiguration i)
{
i.HasTableAnnotation("SoftDeleteColumnName", Entity.G etSoftDeleteColumnName());
});
删除ApplicationDbConfiguration
class
编辑上下文的构造函数
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
DbInterception.Add(new SoftDeleteInterceptor());
}
希望对您有所帮助!
ApplicationDbContext.cs 中存在错误:
protected new void OnModelCreating(DbModelBuilder modelBuilder) {...}
您使用的是 "new" 而不是 "override",因此永远不会执行 OnModelCreating(尝试添加一个断点来检查它)。因此 AttributeToTableAnnotationConvention 永远不会运行,也永远不会添加实体注释。
改成
protected override void OnModelCreating(DbModelBuilder modelBuilder) {...}
会成功的
我使用以下教程实现了数据库软删除(将条目标记为已删除的布尔标志):http://www.codeguru.com/csharp/csharp/soft-deleting-entities-cleanly-using-entity-framework-6-interceptors.html
在我看来,这是一个非常好的实现,因为一旦设置好软删除,只需添加一个 [SoftDelete("IsDeleted")]
注释即可将其应用于模型。问题是到目前为止它还没有工作。
来源似乎是可靠的,他们甚至发布了他们解决方案的示例:https://github.com/rakeshbabuparuchuri/EFExpensionPoints
如果我在对我的项目应用软删除时做错了什么,你能看看我的代码吗?
这是模特:
[SoftDelete("IsDeleted")]
public class BC_Instance
{
public int ID { get; set; }
public bool IsDeleted { get; set; }
}
ApplicationDbContext.cs:
namespace bcplatform2.Models
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
// Add a DbSet for each one of your Entities
//public DbSet<VirtualGuest> VirtualGuests { get; set; }
public DbSet<BC_Instance> BiocloudInstances { get; set; }
static ApplicationDbContext()
{
Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected new void OnModelCreating(DbModelBuilder modelBuilder)
{
var conv = new AttributeToTableAnnotationConvention<SoftDeleteAttribute, string>(
"SoftDeleteColumnName",
(type, attributes) => attributes.Single().ColumnName);
modelBuilder.Conventions.Add(conv);
}
}
}
ApplicationDbConfiguration.cs
namespace bcplatform2.DAL
{
public class ApplicationDbConfiguration : DbConfiguration
{
public ApplicationDbConfiguration()
{
AddInterceptor(new SoftDeleteInterceptor());
}
}
}
SoftDeleteAttribute.cs:
namespace bcplatform2.Helpers
{
public class SoftDeleteAttribute : Attribute
{
public SoftDeleteAttribute(string column)
{
ColumnName = column;
}
public string ColumnName { get; set; }
public static string GetSoftDeleteColumnName(EdmType type)
{
MetadataProperty annotation = type.MetadataProperties
.Where(p => p.Name.EndsWith("customannotation:SoftDeleteColumnName"))
.SingleOrDefault();
return annotation == null ? null : (string)annotation.Value;
}
}
}
SoftDeleteInterceptor.cs
我注意到SoftDeleteAttribute.GetSoftDeleteColumnName(deleteCommand.Target.VariableType.EdmType)
没有找到软删除属性,returns为空。但是不知道为什么。
namespace bcplatform2.Helpers
{
public class SoftDeleteInterceptor : IDbCommandTreeInterceptor
{
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
{
if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
{
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 setClauses = new List<DbModificationClause>();
var table = (EntityType)deleteCommand.Target.VariableType.EdmType;
if (table.Properties.Any(p => p.Name == column))
{
setClauses.Add(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,
setClauses.AsReadOnly(),
null);
interceptionContext.Result = update;
}
}
}
}
}
}
IdentityConfig.cs
public class ApplicationDbInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
InitializeIdentityForEF(context);
base.Seed(context);
}
//Create User=Admin@Admin.com with password=Admin@123456 in the Admin role
public static void InitializeIdentityForEF(ApplicationDbContext db)
{
//Initialize users and roles...
}
}
好吧,我觉得你的代码不错。也许有一个小错误正在破坏您的应用程序。你可以试试这个:
从
BC_Instance
中删除 编辑
OnModelCreating
方法AttributeToTableAnnotationConvention<SoftDeleteAttribute, string> conv = new AttributeToTableAnnotationConvention<SoftDeleteAttribute, string>( "SoftDeleteColumnName", (type, attributes) => attributes.Single().ColumnName); modelBuilder.Conventions.Add(conv); //this will dynamically add the attribute to all models modelBuilder.Types().Configure(delegate(ConventionTypeConfiguration i) { i.HasTableAnnotation("SoftDeleteColumnName", Entity.G etSoftDeleteColumnName()); });
删除
ApplicationDbConfiguration
class编辑上下文的构造函数
public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) { DbInterception.Add(new SoftDeleteInterceptor()); }
SoftDeleteAttribute
希望对您有所帮助!
ApplicationDbContext.cs 中存在错误:
protected new void OnModelCreating(DbModelBuilder modelBuilder) {...}
您使用的是 "new" 而不是 "override",因此永远不会执行 OnModelCreating(尝试添加一个断点来检查它)。因此 AttributeToTableAnnotationConvention 永远不会运行,也永远不会添加实体注释。
改成
protected override void OnModelCreating(DbModelBuilder modelBuilder) {...}
会成功的