5

Estoy utilizando Entity Framework 4.3.1 con un enfoque Code First. Además, estoy usando LinqKit para usar PredicateBuilder.Código Entity Framework Primer predicado 4.3/LINQKit para la tabla relacionada

Si tengo tablas de este modo:

ubicación, la zona horaria (Muchos: 1)

..y me gustaría tener algo así:

Expression<Func<TimeZone, bool>> pred = PredicateBuilder.True<TimeZone>(); 
pred = pred.And(tz => tz.TimeZoneCode == "EST"); 

List<Location> locations = context.Locations 
    .AsExpandable().Where(pred) 
    .Select(loc => loc).ToList(); 

esto no funciona, porque el predicado está diseñado para aceptar un TimeZone, pero el método Where() recibe una ubicación.

puedo reescribir el predicado como tal, pero yo no quiero, porque yo quiero tener una fábrica predicado que crea predicados para tipos específicos (no quiero utilizar las propiedades del navegador de esta manera):

Expression<Func<Location, bool>> pred = PredicateBuilder.True<Location>(); 
pred = pred.And(loc => loc.TimeZone.TimeZoneCode == "EST"); 

Qué sintaxis podría usar (si existe) para usar el predicado como construido en el primer ejemplo, donde toma una ZonaTiempo, en lugar de tener que tomar una Ubicación y recorrer el árbol a través de las propiedades de navegación (ya que menos reutilizable). Sería bueno si hubiera una manera de aprovechar el conocimiento que EF tiene sobre las propiedades de navegación en primer lugar, y ser capaz de usar un predicado con alcance del tipo de la propiedad de navegación.

Respuesta

4

Después de aproximadamente una semana de luchar, descubrí que de hecho puedes hacer esto. Los pasos son:

  1. definir un predicado que es la consulta de su propiedad interno (subPredicate)
  2. Invoke que subPredicate desde el interior de otro predicado (predicate), en contra de la propiedad del objeto padre.
  3. Expand su predicate cuando lo usa en su cláusula Where.

Aquí está el código revisado por su ejemplo:

var subPredicate = PredicateBuilder.True<TimeZone>(); 
subPredicate = subPredicate.And(tz => tz.TimeZoneCode == "EST"); 

var predicate = PredicateBuilder.True<Location>(); 
predicate = predicate.And(l => subPredicate.Invoke(l.TimeZone)); 

List<Location> locations = context.Locations 
    .AsExpandable().Where(pred.Expand()) 
    .Select(loc => loc).ToList(); 
+0

gracias por la actualización! ¿Puede agregar información sobre si este predicado se aplica o no al servidor, a través de LINQ/LINQKit alimentando EF algo que puede traducir a SQL, o se aplica fuerza bruta internamente en EF en un conjunto de datos sin filtrar? –

+0

@PittsburghDBA esto está dando como resultado una llamada a la base de datos a través de EF, traduciéndose a SQL. – Grinn

+0

¡Gracias por este excelente seguimiento! –

1

Solo para actualizar esto: resulta que la intención de este tipo de predicados es filtrar la entidad primaria. El concepto mental es: decidir qué entidades te gustaría devolver y devolverlas. EF aparentemente no está diseñado para este tipo de aplicación de predicados profundos en entidades secundarias.

Una persona (no recuerdo dónde) hizo un gran comentario: si los niños fueron precargados, no esperaría una colección parcialmente cargada. Por lo tanto, no tendría sentido tener una entidad de Factura, por ejemplo, sino solo la mitad de las Líneas de Factura.

Lo que quería lograr era más como EXISTS() o IN(), donde podría decir "Dame todas las facturas donde haya líneas de factura para tipos de productos 'Tuercas' y 'Tornillos'". Esto es factible, pero puede que tenga que aplicar LINQ o componer su propio objeto. La intención de EF de la caja es entregarle la Factura, y luego puede cargar las Líneas de Factura de forma perezosa o impaciente, pero no usarlas como un filtro directo de la base de datos.

Hay algunas construcciones que vi para lograr algo cercano, pero la sintaxis se vuelve muy inmanejable muy rápidamente.

No luche contra el ayuntamiento.

+0

estoy en este escenario ... después de un montón de lectura y ensayo y error de codificación también he learn't no luchar contra el sistema, de lo contrario se obtiene un código complejo y feo. Ugh !!! EF & PredicateBuilder es/son bueno para las 'obras' de las entidades primarias. ¿Qué terminaste haciendo con respecto a las entidades anidadas? Estoy en una encrucijada ahora, decidiendo qué hacer a continuación. (Me doy cuenta de que han pasado 2 años desde tu respuesta). –

+0

Abandonamos EF y ahora usamos SQLClient. Ninguna de estas plataformas ORM puede competir con ADO.Net en términos de rendimiento sin procesar, sin importar los problemas de estos predicados. –

+0

@ThomasVeil eche un vistazo a las diferencias brutales descritas aquí: https://web.archive.org/web/20131205132904/http://ormbattle.net/ –

Cuestiones relacionadas