从数据库加载数据时,我可以拦截实体框架吗?

时间:2013-02-14 16:25:52

标签: entity-framework

我们有一个多层应用程序,其中所有存储库都基于(自行开发的)GenericRepository基类(其中T是模型中的实体),它公开了诸如GetContext(),GetObjectSet()之类的方法。等等。我们允许从此继承的存储库访问上下文,因为它们需要调用Include(),因为我们正在通过WCF服务传递数据,因此需要急切地加载所有相关实体。

我们所有的实体都实现了一个具有Active bool属性的接口,我们要做的是拦截查询的执行,并对Active属性进行过滤,以便任何查询只返回设置为真。

可以这样做吗?在基于EF构建的Lightswitch中,您可以捕获的事件会在查询执行的深度中被触发,并允许您执行此类过滤。我在EF本身找不到允许这样做的任何内容。

任何想法?感谢

2 个答案:

答案 0 :(得分:1)

我能想到的最佳方式是让您的存储库方法接受表达式(即Expression<Func<T, bool>> predicate)。这样,您可以在实际存储库本身中执行所有查询(因此不允许以任何方式访问数据层逻辑的客户端代码),在从存储库方法返回之前可以向其添加Where只抓住那些活跃的。

我使用的这种风格的一个例子如下:

   public IQueryable<T> Grab(Expression<Func<T, bool>> predicate)
   {
     return DbSet.Where(predicate);
   }

其中DbSet是您尝试查询的实际表。这样你可以在它的末尾添加.Where(x => x.Active),让它不对数据库执行(谢谢,延迟执行!)但仍然可以获得你正在寻找的确切记录。

答案 1 :(得分:1)

在EF 5中,IncludeIQueryable上的扩展方法,因此您可以这样做:

var query = dbSet.Where( o => o.IsActive ).Include( ... )

这意味着,您不必从通用存储库返回DbSet<T> - 应该可以返回IQueryable<T>

如果这符合您的要求,您可以在通用存储库方法中添加Where子句:

partial class GenericRepository<T>
{
  public IQueryable<T> Query( bool includeInactive = false )
  {
    return ctx.Set<T>().Where( o => includeInactive || o.IsActive );
  }
}