2010-09-15 21 views
10

Ich möchte eine Entität und ihre Kinder bedingt laden (ich möchte nur die Kinder eifrig laden, wenn die child.IsActive == wahr). Wie führe ich Folgendes durch?Bedingtes Eager-Laden?

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

HINWEIS: Ich möchte keinen anonymen Typ zurückgeben.

Danke.

Antwort

9

Eine Möglichkeit dafür ist,:

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


Allerdings könnten Sie nicht wie die Idee einen anonymen Typ zurück, dann würde ich vorschlagen, es auf diese Weise zu kodieren:

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

Ich habe vergessen zu erwähnen, dass ich keinen anonymen Typ zurückgeben möchte ... Ich muss ein Objekt (oder eine Sammlung) vom Typ tblParent zurückgeben. –

+0

Sicher, ich habe ein weiteres Code-Snippet hinzugefügt, das Ihnen ein stark typisiertes Parent-Objekt gibt, das alle untergeordneten Elemente enthält, die den Kriterien entsprechen. Bitte guck dir das an. –

+1

Das macht Sinn ... wir sind jedoch aus dem Bereich des eifrigen Ladens ausgezogen. –

1

Entity Framework 6 führt die Interception http://entityframework.codeplex.com/wikipage?title=Interception ein, mit der die SQL angepasst werden kann, um die untergeordneten Elemente zu filtern.

Vor der Ausführung Ihrer Anfrage ein Abfangjäger hinzuzufügen und zu entfernen, wenn es nicht relevant ist:

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

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

DbInterception.Remove(interceptor); 

Probe Interceptor, die "[Aktiv] = 1 Und" wenn loading Tags ergänzt:

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) 
    { 
    } 
} 
+0

Während ich es nicht wirklich mag, Entity SQL manuell zu ändern, funktioniert das perfekt. Damit muss ich meinen Anfragecode nach dem Soft Deletion nicht ändern. +1 – Nathan

1

sein in der Lage, Filter anzuwenden, bessere Option verwendet Explizit zusammen mit laden Query() anstelle von Eager loading:

Die Query-Methode bietet Zugriff auf die zugrunde liegende Abfrage, die das Entity Framework beim Laden verwandter Entitäten verwendet. Außerdem müssen Sie Lazy Loading für die Navigationseigenschaft deaktivieren (Virtual-Schlüsselwort entfernen) andernfalls wird die Sammlung automatisch durch das Lazy-Laden geladen, das Ihren Filter ignoriert.