微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

用于软删除的 EF 6.0 拦截器,具有多对多关系

如何解决用于软删除的 EF 6.0 拦截器,具有多对多关系

我正在使用 EF 6.0 Code First 实现软删除。我已经使用 2016 年的这篇博文实现了:

[https://marisks.net/2016/02/27/entity-framework-soft-delete-and-automatic-created-modified-dates/][1]

然而,它不包括多对多关系。我在任何地方都找不到处理多对多的帮助。我已经用谷歌搜索了我的大脑。

以下是我的课程的相关部分: 密钥分发

public class Keydistribution : ITypeNameProvider
    {
        public Keydistribution()
        {
            EquipmentAreas = new List<EquipmentArea>();
            ///...
        }

        ///...
        public virtual List<EquipmentArea> EquipmentAreas { get; set; }
        ///...
        public virtual bool Active { get; set; } = true;
        ///...        
    }

设备面积

public class EquipmentArea : ITypeNameProvider
    {
        public EquipmentArea()
        {
            Keydistributions = new List<Keydistribution>();
            ///...
        }

        ///...
        public virtual List<Keydistribution> Keydistributions { get; set; }
        public virtual bool Active { get; set; } = true;
        ///...
    }

我已经映射了连接表,如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<EquipmentArea>().HasMany(x => x.Keydistributions).WithMany(x => x.EquipmentAreas).Map
            (x => x.ToTable("dispatchEquipmentArea_Keydistribution").MapLeftKey("dispatchEquipmentArea_Id"));
        ///...
    }

我也尝试过 .MapRightKey。

这是我的拦截代码

public class SoftDeleteInterceptor : IDbCommandTreeInterceptor
{
    public const string ActiveColumnName = "Active";

    public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
    {
        if (interceptionContext.OriginalResult.DataSpace != DataSpace.sspace && 
            interceptionContext.OriginalResult.DataSpace != DataSpace.CSpace)  //Added CSpace to pick up association
        {
            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 HandleDeleteCommand(DbDeleteCommandTree deleteCommand)
    {
        ///...
    }
    private static DbCommandTree HandleQueryCommand(DbQueryCommandTree queryCommand)
    {
        DbExpression newQuery = queryCommand.Query.Accept(new SoftDeleteQueryVisitor());
        return new DbQueryCommandTree(
            queryCommand.MetadataWorkspace,queryCommand.DataSpace,newQuery);
    }

    public class SoftDeleteQueryVisitor : DefaultExpressionVisitor
    {
        public override DbExpression Visit(DbScanExpression expression) 
        {
            try
            {
                BuiltInTypeKind type = expression.Target.BuiltInTypeKind;
                if (type == BuiltInTypeKind.AssociationSet)  //Here is where I need new binding
                {
                    return base.Visit(expression);
                    //New binding needed here.  Cannot figure out how to do on an AssociationSet vs an EntityType
                }
                else
                {

                    var table = (EntityType)expression.Target.ElementType;
                    if (table.Properties.All(p => p.Name != ActiveColumnName))
                    {
                        return base.Visit(expression);
                    }
                    ///SKIP MANY TO MANY TABLES HERE
                    else if (table.Name == "dispatchEquipmentArea_Keydistribution" ||
                        table.Name == "EquipmentArea" ||
                        table.Name == "Keydistribution")
                    {
                        return base.Visit(expression);
                    }
                    else
                    {
                        DbExpressionBinding binding = expression.Bind();
                        return binding.Filter(
                            binding.VariableType
                                .Variable(binding.VariableName)
                                .Property(ActiveColumnName)
                                .NotEqual(DbExpression.FromBoolean(false)));
                    }
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }
}

多对多关系的每一端都有一个“活动”列,以及它们之间的连接表。因此它们之间的关系也可以是 Active/Inactive。

我在调试过程中仔细研究了这些对象,但我不知道如何更改 AssociationSet 以将“Where Active = true”放到它上面。我已经坚持了这么久。请帮忙。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。