使用数据库拦截器的实体框架软删除实现不起作用 [英] Entity Framework soft delete implementation using database interceptor not working

查看:109
本文介绍了使用数据库拦截器的实体框架软删除实现不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已使用以下教程实现了数据库软删除(将条目标记为已删除的布尔标志):

I have implemented a database soft delete (a boolean flag that marks entries as deleted) using the following tutorial: http://www.codeguru.com/csharp/csharp/soft-deleting-entities-cleanly-using-entity-framework-6-interceptors.html

在我看来,这是一个很好的实现,因为一旦设置软删除,只需添加[SoftDelete("IsDeleted")]批注即可将其应用于模型.到目前为止,问题还没有解决.

It seems to me a very good implementation because once set up soft delete is applied to a model simply by adding a [SoftDelete("IsDeleted")] annotation. Problem is so far it is not working.

消息来源似乎可靠,他们甚至发布了解决方案的示例: https://github.com/rakeshbabuparuchuri/EFExpensionPoints

The source appears to be reliable, and they even published an example of their solution: https://github.com/rakeshbabuparuchuri/EFExpensionPoints

在将软删除应用于项目时,如果我做错了什么,可以看看我的代码吗?

Can you have a look at my code in case I did something wrong when applying the soft delete to my project?

这是模型:

[SoftDelete("IsDeleted")]
public class BC_Instance
{
    public int ID { get; set; }
    public bool IsDeleted { get; set; }
}

ApplicationDbContext.cs:

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

ApplicationDbConfiguration.cs

namespace bcplatform2.DAL
{
    public class ApplicationDbConfiguration : DbConfiguration
    {
        public ApplicationDbConfiguration()
        {
            AddInterceptor(new SoftDeleteInterceptor());
        }
    }
}

SoftDeleteAttribute.cs:

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

SoftDeleteInterceptor.cs

我注意到SoftDeleteAttribute.GetSoftDeleteColumnName(deleteCommand.Target.VariableType.EdmType)找不到软删除属性,并返回null.但我不知道为什么.

I noticed that SoftDeleteAttribute.GetSoftDeleteColumnName(deleteCommand.Target.VariableType.EdmType) does not find the soft delete attribute and returns null. But I don't know why.

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

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...
    }
}

推荐答案

ApplicationDbContext.cs中存在错误:

There is a bug in ApplicationDbContext.cs:

protected new void OnModelCreating(DbModelBuilder modelBuilder) {...}

您使用的是"new"而不是"override",因此永远不会执行OnModelCreating(尝试添加断点进行检查).因此AttributeToTableAnnotationConvention永远不会运行,也永远不会添加实体注释.

You are using "new" instead of "override" so OnModelCreating is never executed (try to add a breakpoint to check it). So AttributeToTableAnnotationConvention never runs and entity annotation is never added.

更改为

protected override void OnModelCreating(DbModelBuilder modelBuilder) {...}

将使其正常工作

这篇关于使用数据库拦截器的实体框架软删除实现不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆