2010-09-15 17 views
10

Quiero cargar una entidad y sus hijos de forma condicional (solo quiero cargar ansiosamente los elementos secundarios cuando child.IsActive == true). ¿Cómo realizo lo siguiente?¿Condicional carga ansiosa?

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

NOTA: No deseo devolver un tipo anónimo.

Gracias.

Respuesta

9

Una forma de hacerlo es:

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


Sin embargo, es posible que no le gusta la idea de devolver un tipo anónimo, entonces sugeriría que codificar de esta manera:

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

Olvidé mencionar que no quiero devolver un tipo anónimo ... Necesito devolver un objeto (o colección) de tipo tblParent. –

+0

Claro, agregué otro fragmento de código que le proporciona un fuerte objeto Parent escrito que contiene todos los elementos secundarios que coinciden con los criterios. Por favor échale un vistazo. –

+1

Esto tiene sentido ... sin embargo, nos hemos movido del reino de la carga ansiosa. –

1

Entity Framework 6 introduce Interception http://entityframework.codeplex.com/wikipage?title=Interception que se puede usar para ajustar el SQL para filtrar los elementos secundarios.

Antes de ejecutar la consulta añadir un interceptor y quitar cuando no es relevante:

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

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

DbInterception.Remove(interceptor); 

interceptor de la muestra, que añade "[Activo] = 1 Y" cuando se carga Etiquetas:

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

Aunque realmente no me gusta modificar manualmente el SQL de Entity, esto funciona perfectamente. Con esto no tengo que modificar mi código de consulta en absoluto después de implementar la eliminación de software. +1 – Nathan

1

Ser capaz de aplicar filtro, la mejor opción es usar Explicitamente cargando junto con Consulta() en lugar de Ansioso cargando:

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

El método de consulta proporciona acceso a la consulta subyacente que Entity Framework utilizará al cargar entidades relacionadas. También necesita desactivar la carga diferida para la propiedad de navegación (eliminar la palabra clave Virtual) de lo contrario la colección se carga automáticamente por la carga diferida que ignora su filtro.

Cuestiones relacionadas