【问题标题】:How to intercept a SELECT query如何拦截 SELECT 查询
【发布时间】:2015-07-24 21:53:23
【问题描述】:

我正在探索 Entity Framework 7,我想知道是否有办法拦截“SELECT”查询。每次创建、更新或删除实体时,我都会在实体上标记当前日期和时间。

SELECT * 
FROM MyTable
WHERE DeletedOn IS NOT NULL

我希望我的所有 SELECT 查询都排除已删除的数据(请参阅上面的 WHERE 子句)。有没有办法使用 Entity Framework 7 来做到这一点?

【问题讨论】:

  • 我会改用软删除,即位字段Deleted。如果设置为 true,则更新日期时间将显示发生这种情况的时间。有关复杂但完整的解决方案,请参阅 github.com/rowanmiller/Demo-TechEd2014
  • 该示例似乎适用于 EF6,而不是 EF7。
  • 当然他们还没有在 EF 7 中实现命令拦截器。我开始讨厌这个半生不熟的版本,即使它仍然是一个预发布版本。不过,我认为最好遵循标准的软删除方法,但我还不知道如何拦截 EF7 命令。
  • 您提供的 where 子句只会导致任何数据被删除,除非我读错了?您的意思是使用 Is Null 吗?

标签: entity-framework entity-framework-core


【解决方案1】:

我不确定您的底层基础架构是什么样的,以及您的应用程序和实体框架之间是否有任何抽象。假设您正在使用DbSet<T>,您可以编写一个扩展方法来排除已删除的数据。

        public class BaseEntity
        {
                public DateTime? DeletedOn { get; set; }
        }
        public static class EfExtensions
            {
                public static IQueryable<T> ExcludeDeleted<T>(this IDbSet<T> dbSet) 
                    where T : BaseEntity
                {
                    return dbSet.Where(e => e.DeletedOn == null);
                }
            }
      //Usage
      context.Set<BaseEntity>().ExcludeDeleted().Where(...additional where clause).

【讨论】:

  • 这不是我真正想要的。我要求一种始终在查询中包含 DeletedOn == Null 的方法,以防止软删除的行出现在结果中。
  • @Martin,我误解了你在问什么。与其拦截 SQL,不如在底层基础架构中包含该过滤器。你看过使用规范模式吗?您的基础架构是什么样的?您在 EF 和您的应用程序之间有什么额外的抽象吗?
  • @Martin,我用可能的解决方案更新了我的答案。
【解决方案2】:

我也有同样的问题。我正在尝试拦截读取查询,例如; select, where 等以查看返回的结果集。不幸的是,在 EF Core 中,您没有等效项来覆盖读取查询的 SaveChanges。

但是,您仍然可以使用 Entity Framework Core 连接到 commandExecuting 和 commandExecuted,使用

 var listener = _context.GetService<DiagnosticSource>();
(listener as DiagnosticListener).SubscribeWithAdapter(new CommandListener());

并使用以下两种方法创建一个类

   public class CommandListener
    {
        [DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting")]
        public void OnCommandExecuting(DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, bool async, DateTimeOffset startTime)
        {
            //do stuff. 
        }

        [DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted")]
        public void OnCommandExecuted(object result, bool async)
        {
           //do stuff. 
        }
    }

但是,这些是高级拦截器,因此您将无法查看返回的结果集(使其在您的情况下无用)。

我推荐两件事,首先去投票“Hooks to intercept and modify queries on the fly at high and low level的实现投票:https://data.uservoice.com/forums/72025-entity-framework-core-feature-suggestions/suggestions/1051569-hooks-to-intercept-and-modify-queries-on-the-fly-a

其次,您可以通过使用拦截器来使用 PostSharp(一种商业产品):属性的 LocationInterceptionAspect 或方法的 OnMethodBoundaryAspect。

【讨论】:

    猜你喜欢
    • 2017-02-15
    • 2020-02-21
    • 1970-01-01
    • 1970-01-01
    • 2021-10-05
    • 2016-05-19
    • 2015-08-31
    • 2014-02-04
    • 2021-05-21
    相关资源
    最近更新 更多