有条件的急切加载?

时间:2010-09-15 14:05:50

标签: entity-framework entity-framework-4

我想有条件地加载一个实体和它的子项(我只想在child.IsActive == true时加载子项。)我该如何执行以下操作?

var parent = 
    from p in db.tblParents.Include("tblChildren") <-- where tblChildren.IsActive == true
    where p.PrimaryKey == 1
    select p;

注意:我不想返回匿名类型。

感谢。

3 个答案:

答案 0 :(得分:9)

这样做的一种方法是:

var parent = from p in db.tblParents where p.PrimaryKey == 1
             select new {
                 Parent = p,
                 Children = p.tblChildren.Where(c => c.IsActive == true)
             }.ToList();


但是,您可能不喜欢返回匿名类型的想法,然后我建议以这种方式编写代码:

var parent = (from p in db.tblParents where p.PrimaryKey == 1).Single();
var childrens = ctx.Contacts.Where(c => c.ParentID == 1 && c.IsActive == true);
foreach (var child in childrens) {
   parent.tblChildren.Add(child);
}

答案 1 :(得分:2)

为了能够应用过滤器,更好的选择是使用明确加载以及 Query()而不是 Eager 加载:

sharedpreferences

Query方法提供对实体框架在加载相关实体时将使用的基础查询的访问。此外,您还需要关闭延迟加载以获取导航属性(删除虚拟关键字),否则将通过延迟加载自动加载集合,忽略您的过滤器。

答案 2 :(得分:1)

实体框架6引入了拦截http://entityframework.codeplex.com/wikipage?title=Interception,可用于调整SQL以过滤子项。

在执行查询之前,添加一个拦截器,并在它不相关时删除:

var interceptor = new ActiveTagsInterceptor();
DbInterception.Add(interceptor);

documents = context.Documents
                .AsQueryable()
                .Include(d => d.Tags)

DbInterception.Remove(interceptor);

示例拦截器添加&#34; [Active] = 1和&#34;加载标签时:

public class ActiveTagsInterceptor : IDbCommandInterceptor
{
    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
    }

    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
    }

    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        // [Tag] AS [Extent6] ON   => [Tag] AS [Extent6] ON [Extent6].[Active] = 1 And 
        const string pattern = "\\[Tag\\]\\sAS\\s\\[([\\w]+)\\]\\sON";
        const string replacement = "$& [$1].[Active] = 1 And ";
        command.CommandText = Regex.Replace(command.CommandText, pattern, replacement);
    }

    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
    }

    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
    }

    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
    }
}