2011-11-30 10 views
6

asume que tienen estas entidades EF generada simplificados ...Entity Framework - Condición selectivo en la navegación por la propiedad Incluye

public class PurchaseOrder 
{ 
    public int POID {get;set;} 
    public int OrderID {get;set;} 
    public int VendorID {get;set;} 
    public IEnumerable<Order> Orders {get;set;} 
} 

public class Order 
{ 
    public int OrderID {get;set;} 
    public decimal Price {get;set;} 
    public IEnumerable<Item> Items {get;set;} 
} 

public class Item 
{ 
    public int OrderID {get; set;} 
    public string SKU {get;set;} 
    public int VendorID {get;set;} 
    public Order Order {get;set;} 
} 

lógica de negocios:

Una orden puede tener múltiples OP, uno para cada proveedor distinto en el pedido (los proveedores se determinan a nivel de artículo).

¿Cómo puedo incluir entidades secundarias de forma selectiva?

Al consultar las OP, quiero incluir automáticamente las entidades infantiles para el pedido y el artículo.

puedo lograr esto, usando include() ...

Context.PurchaseOrders.Include("Orders.Items"); 

Esto es trabajo y tira hacia atrás entidades relacionadas, pero, que sólo quieren incluir entidades artículo cuyo IdProveedor coincide con el de la IdProveedor Entidad PurchaseOrder.

Con el SQL tradicional, simplemente lo incluiría en la condición JOIN, pero EF los compila internamente.

¿Qué magia de LINQ puedo usar para decirle a EF que aplique la condición, sin crear manualmente las UNIONES entre las entidades?

Respuesta

2

No puede seleccionar de forma selectiva ciertas entidades secundarias que coinciden con una determinada condición. Lo mejor que puede hacer es filtrar manualmente los pedidos relevantes usted mismo.

public class PurchaseOrder 
{ 
    public int POID {get;set;} 
    public int OrderID {get;set;} 
    public int VendorID {get;set;} 
    public IEnumerable<Order> Orders {get;set;} 

    public IEnumerable<Order> MatchingOrders { 
     get { 
      return this.Orders.Where(o => o.VendorId == this.VendorId); 
     } 
    } 
} 
+0

espero ver esto como una mejora de funciones en el futuro. – ctorx

+0

@Matthew - serían una gran adición al framework –

+0

más de cinco años y aún nada ... asombroso, no está mal para una de las características más útiles que EF podría tener ... -.- ' – Shockwaver

3

No puede. EF no permite condiciones para la carga ansiosa. Debe bien utilizar varias consultas como:

var pos = from p in context.PurchaseOrders.Include("Order") 
      where ... 
      select p; 
var items = from i in context.Items 
      join o in context.Orders on new { i.OrderId, i.VendorId} 
       equals new { o.OrderId, o.PurchaseOrder.VendorId } 
      where // same condition for PurchaseOrders 
      select i; 

O puede utilizar la proyección de consulta única:

var data = from o in context.Orders 
      where ... 
      select new 
       { 
        Order = o, 
        PurchaseOrder = o.PurchaseOrder, 
        Items = o.Items.Where(i => i.VendorId == o.PurchaseOrder.VendorId) 
       }; 
1

podría utilizar el IQueryable-Extensiones aquí:

https://github.com/thiscode/DynamicSelectExtensions

El La extensión crea dinámicamente un tipo anónimo. Esto se usará para la proyección según lo descrito por @ Ladislav-Mrnka.

A continuación, puede hacer esto:

var query = query.SelectIncluding(new List<Expression<Func<T,object>>>>(){ 

//Example how to retrieve only the newest history entry 
x => x.HistoryEntries.OrderByDescending(x => x.Timestamp).Take(1), 

//Example how to order related entities 
x => x.OtherEntities.OrderBy(y => y.Something).ThenBy(y => y.SomeOtherThing), 

//Example how to retrieve entities one level deeper 
x => x.CollectionWithRelations.Select(x => x.EntityCollectionOnSecondLevel), 

//Of course you can order or subquery the deeper level 
//Here you should use SelectMany, to flatten the query 
x => x.CollectionWithRelations.SelectMany(x => x.EntityCollectionOnSecondLevel.OrderBy(y => y.Something).ThenBy(y => y.SomeOtherThing)), 

}); 
Cuestiones relacionadas