2012-02-15 13 views
5

que tienen las siguientes dos tablas:NHibernate - Izquierda une

Empleo areaid, JobNo (clave compuesta)

Registros LOGID, areaid, JobNo

que necesitan para obtener todos los puestos de trabajo que no tienen ningún registro asociado con ellos. En SQL podría hacer:

SELECT Jobs.AreaID, 
     Jobs.JobNo 
FROM Jobs 
     LEFT JOIN Logs 
      ON Jobs.AreaID = Logs.AreaID 
      AND Jobs.JobNo = Logs.JobNo 
WHERE Logs.LogID is null 

Pero no estoy seguro de cómo lograr esto con NHibernate. ¿Alguien podría ofrecer alguna sugerencia?

Éstos son mis asignaciones:

<class name="Job" table="Jobs"> 
    <composite-key name="Id"> 
     <key-property name="JobNo"/> 
     <key-many-to-one name="Area" class="Area" column="AreaID"/> 
    </composite-key> 
</class> 

<class name="Log" table="Logs"> 
    <id name="Id" column="LogID"> 
     <generator class="identity"/> 
    </id> 
    <property name="JobNo"/> 
    <many-to-one name="Area" class="Area" column="AreaID"/> 
</class> 

Gracias

Actualizar

OK, he modificado la respuesta de Nosila un poco, y esto ahora está haciendo lo que quería:

Log logs = null; 

return session.QueryOver<Job>() 
    .Left.JoinAlias(x => x.Logs,() => logs) 
    .Where(x => logs.Id == null) 
    .List<Job>(); 

También tuve que agregar esto a mi trabajo mapeo:

<bag name="Logs"> 
    <key> 
     <column name="JobNo"></column> 
     <column name="DivisionID"></column> 
    </key> 
    <one-to-many class="Log"/> 
</bag> 

Gracias por la ayuda. :)

+0

¿Puede publicar la consulta que tiene ahora? – Nosila

+0

La consulta SQL anterior es actualmente lo que estoy usando. Estoy aprendiendo NH en este momento y estoy tratando de convertir una pequeña aplicación para usarlo. – Tom

+0

¿Tiene sus asignaciones creadas? Además, alguien me corrige si me equivoco, pero creo que necesita NHibernate 3.2 para agregar condiciones a su unión (utilizando la API 'QueryOver', de todos modos). – Nosila

Respuesta

6

No estoy familiarizado con los identificadores compuestos, ya que no los uso, así que, por lo que sé, NHibernate creará automáticamente la unión izquierda adecuada. No obstante, la consulta (no probada) a continuación debe comenzar.

Job jobAlias = null; 
Log logAlias = null; 
YourDto yourDto = null; 

session.QueryOver<Job>() 
    // Here is where we set what columns we want to project (e.g. select) 
    .SelectList(x => x 
     .Select(x => x.AreaID).WithAlias(() => jobAlias.AreaID) 
     .Select(x => x.JobNo).WithAlias(() => jobAlias.JobNo) 
    ) 
    .Left.JoinAlias(x => x.Logs,() => logAlias, x.JobNo == logAlias.JobNo) 
    .Where(() => logAlias.LogID == null) 
    // This is where NHibernate will transform what you have in your `SelectList()` to a list of objects 
    .TransformUsing(Transformers.AliasToBean<YourDto>()) 
    .List<YourDto>(); 

public class YourDto 
{ 
    public int AreaID { get; set; } 
    public int JobNo { get; set; } 
} 

Nota: Necesita NHibernate 3.2 para establecer condiciones de unión.

+1

Gracias. Tendré que reflexionar sobre esto (hay algunos errores). También parece extremadamente complejo para una consulta tan simple. – Tom

+0

@Tom Estoy de acuerdo con la complejidad, escribir esto en SQL sería mucho más simple. Siento que la abstracción de ORM se está yendo de las manos. – Jafin

4
Job job = null; 
var jobsWithoutLogs = session.QueryOver(() => job) 
    .WithSubquery.WhereNotExists(QueryOver.Of<Log>() 
     .Where(log => log.Job == job) 
     .Select(Projections.Id())) 
    .List() 

Actualización: he visto que ha agregado la asignación. El código anterior solo funciona para la siguiente asignación

<class name="Log" table="Logs"> 
    <id name="Id" column="LogID"> 
     <generator class="identity"/> 
    </id> 
    <many-to-one name="Job" > 
     <column name="JobNo"/> 
     <column name="AreaID"/> 
    <many-to-one /> 
</class> 
+0

Agradable. Me gusta esta solución mejor. – Nosila

+0

Esto parece más fácil, aunque obtengo el error "No se pueden usar subconsultas en un criterio sin proyección". Además, ¿va a ser una consulta más costosa ya que está utilizando subconsultas en lugar de una simple combinación a la izquierda? – Tom

+0

1) proyección añadida. 2) No creo que sea más caro ya que está haciendo lo mismo. puedes consultar el plan de consulta – Firo