【问题标题】:Entity Framework: Filtering Navigation Properties实体框架:过滤导航属性
【发布时间】:2013-12-03 03:12:17
【问题描述】:

我正在使用实体框架 - 代码优先,我有下一个上下文(至少是提取):

public class TestContext : DbContext
{
    public DbSet<User> Users { get; set}
    public DbSet<Book> Books { get; set}
}

在用户的类中我有这个导航属性:

public virtual Collection<Book> Books { get; set}

ergo,一个用户有很多书。 问题是我想过滤书籍,但由于我的数据库中有 500.000 本书,我无法将所有书籍都放入内存并稍后过滤它们。我需要使用过滤语句对数据库执行查询。

当我这样做时:

// Doesn't matter how i get the user...
var allBooks = user.Books; // Here it brings all the books of the user
var activeBooks = allBooks.Where(n => n.Active);

我认为您可以看到问题...我想在执行之前将过滤器添加到查询中...但我不知道该怎么做。

我也将不胜感激。

谢谢。

编辑:

另一个具有显式上下文的示例,可能是清楚的事情......

IQueryable<Course> query = new TestContext().Set<User>(); // It doesn't run the query yet.
var a = query.Where(n => n.Active); // Here it runs the query!
var b = a.ToList(); // The items was on memory...

【问题讨论】:

    标签: .net entity-framework ef-code-first


    【解决方案1】:

    我个人认为您的操作没有任何问题。在 GetEnumerator() 之前,书籍列表不会被加载到内存中,无论是显式地还是通过调用 foreach 等。

    var activeBooks = user.Books.Where(n => n.Active); //still iqueryable
    var inMemory = activeBooks.ToList(); //executes iqueryable
    //or
    foreach(var book in activeBooks)
        {
    
        } 
    

    编辑

    您可能想阅读 IQueryable http://msdn.microsoft.com/en-us/library/system.linq.iqueryable(v=vs.110).aspx

    "IQueryable 接口继承了 IEnumerable 接口,因此如果它表示一个查询,则可以枚举该查询的结果。枚举导致执行与 IQueryable 对象关联的表达式树。"执行表达式树的定义" 特定于查询提供程序。例如,它可能涉及将表达式树转换为底层数据源的适当查询语言。调用 Execute 方法时会执行不返回可枚举结果的查询。"

    这意味着为了执行查询,您必须枚举可枚举对象。

    IQueryable<Course> query = new TestContext().Set<User>(); // It doesn't run the query yet.
    
    IQueryable<Course> a = query.Where(n => n.Active); // Not executed yet
    
    IQueryable<Course> c = a.Where(n => n.Title.Contains("Science")); //still not executed
    
    List<Course> b = a.ToList(); //Executes the query
    

    【讨论】:

    • 是的,我知道它应该是这样的,但我正在检查 VS 上的 intelltrace,并且当我访问导航属性时查询正在运行。在您的示例中, user.Books 将带来所有书籍,然后“where”将在内存中过滤它们......
    • 谢谢!解决了!但现在我有另一个问题...导航属性...检查一下:stackoverflow.com/questions/20357511/…
    【解决方案2】:

    使用filtered explicit loading 加载所需书籍:

    dbContext.Entry(user).Collection(u => u.Books).Query().Where(b => b.Active).Load();
    

    【讨论】:

      【解决方案3】:

      我实现了一个解决方案,其中涉及包装 IDbSet 并使用它而不是上下文的普通成员,如下所示:

      public class MyContext : DbContext
      {
          public IDbSet<MyEntity> Entities { get; set; }
      
          public MyContext()
          {
              this.Entities = new FilteredDbSet<MyEntity>(this, x => x.SomeProperty == 1);
          }
      }
      

      FilteredDbSet 类会自动将构造函数中传递的表达式添加到该实体的所有查询中。在http://weblogs.asp.net/ricardoperes/filter-collections-automatically-with-entity-framework-code-first 上查看我的示例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-29
        • 2016-05-29
        相关资源
        最近更新 更多