Entity framework 条件急切加载?

Entity framework 条件急切加载?,entity-framework,entity-framework-4,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; var父项= 从db.tblParents.Include(“tblChildre

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

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

从db.tblParents.Include(“tblChildren”)中的p执行此操作的一种方法是:

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);
}

实体框架6引入了拦截,可用于调整SQL以过滤子级

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

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

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

DbInterception.Remove(interceptor);
加载标签时添加“[Active]=1和”的示例拦截器:

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)
    {
    }
}
public类ActiveTagsInterceptor:IDbCommandInterceptor
{
public void非查询执行(DbCommand命令,DbCommandInterceptionContext interceptionContext)
{
}
public void NonQueryExecuted(DbCommand命令,DbCommandInterceptionContext interceptionContext)
{
}
public void reader执行(DbCommand命令,DbCommandInterceptionContext interceptionContext)
{
//[Tag]AS[Extent6]ON=>[Tag]AS[Extent6]ON[Extent6]。[Active]=1和
常量字符串模式=“\\[Tag\\]\\sAS\\s\\[([\\w]+)\\]\\sON”;
常量字符串替换=“$&[$1].[Active]=1和”;
command.CommandText=Regex.Replace(command.CommandText,pattern,replacement);
}
public void ReaderExecuted(DbCommand命令,DbCommandInterceptionContext interceptionContext)
{
}
public void scalare执行(DbCommand命令、DbCommandInterceptionContext interceptionContext)
{
}
已执行公共空标度(DbCommand命令、DbCommandInterceptionContext interceptionContext)
{
}
}

为了能够应用过滤器,更好的选择是使用显式加载和查询()而不是快速加载:

var parent = db.tblParents.Find(1);
db.Entry(parent).Collection(p => p.tblChildren).Query().
    Where(child => child.IsActive).Load();

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

我忘了提到我不想返回匿名类型。。。我需要返回tblParent类型的对象(或集合)。当然,我添加了另一个代码段,它为您提供了一个强类型的父对象,其中包含符合条件的所有子对象。请看一看。这很有道理。。。然而,我们已经走出了渴望加载的领域。所以我仍然回到了我最初的问题。。。在此期间,我刚刚使用Linq过滤掉内存中的记录……恐怕没有办法使用include实现“条件急切加载”。Include()方法的API就是不是这样设计的。解决方法是利用“过滤投影”或通过实现“两个跟踪查询”来完成,我的代码片段分别介绍了这两种方法。如果我们可以编写这样的代码就好了:Include(“tblChildren”,c=>c.IsActive==true)。这样,在实现软删除之后,我根本不需要修改查询代码+1.