实体框架:过滤导航属性

时间:2013-12-03 03:12:18

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

我正在使用Entity Framework - Code First,我有下一个上下文(至少是一个提取):

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

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

public virtual Collection<Book> Books { get; set}
因此,用户有很多书。 问题是我想要过滤书籍,但由于我在我的数据库上有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...

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

使用filtered explicit loading加载所需的图书:

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

答案 2 :(得分:0)

我实现了一个解决方案,它涉及包装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上的示例。