2010-11-03 19 views
8

Con Linq alle entità, sto tentando di eseguire una query su una tabella dei registri per trovare le righe vicino a una riga corrispondente. Ho problemi con l'aggiunta di una data all'interno della query. Questo è quello che ho finora.Aggiungere una data in Linq alle entità

from 
    l in objectSet.Logs 
let 
    match = objectSet.Logs.Where(whatever).FirstOrDefault() 
where 
     l.Timestamp > (match.Timestamp - twoHours) 
    && l.Timestamp < (match.Timestamp + twoHours) 
select 
    l 

Tralasciando la "qualunque" condizione che trova la riga che mi interessa, "twoHours" è stato un periodo di tempo variabile, una funzione .AddHours() e così via. Non ho trovato il modo giusto in cui EF può generare SQL che aggiunge il valore di un campo (match.Timestamp) a una costante.

La soluzione ovvia è eseguire prima la query "match" e quindi utilizzare il valore letterale in una seconda query, ma ho semplificato l'esempio di codice qui al problema principale (aggiungendo le date nella query) e in realtà la mia domanda è più complessa e questo non sarebbe l'ideale.

Acclamazioni

+0

Ho avuto un problema simile. Il problema è che .AddHours() non ha un equivalente SQL e, quindi, Linq non è in grado di convertirlo in un'espressione SQL. Ho risolto questo problema invocando l'esecuzione ritardata chiamando .ToList() e poi applicando il filtro .AddHours() su una raccolta in memoria. – dotariel

+0

@ XSaint32, questo è doppiamente sbagliato. Ci * è * [un (T) equivalente SQL,] (http://msdn.microsoft.com/en-us/library/ms186819.aspx) e tu * puoi * chiamarlo dall'EF. –

+0

@Craig - Grazie per l'input. Non ero conscio di ciò. – dotariel

risposta

11

È possibile generare un AddHours utilizzando il EntityFunctionsclass.

from 
    l in objectSet.Logs 
let 
    match = objectSet.Logs.Where(whatever).FirstOrDefault() 
where 
     (l.Timestamp > EntityFunctions.AddHours(match.Timestamp, -1 * twoHours)) 
    && // ... 
select 
    l 

Tuttavia, non aspettatevi questo WHERE per essere ottimizzato con un indice a meno che non si dispone di un indice di espressione su colonna.

+0

Impressionante, grazie Craig –

+0

Nota, 'EntityFunctions' è stato contrassegnato come obsoleto. Utilizzare invece la funzione sostitutiva 'DbFunctions' nello spazio dei nomi' System.Data.Entity'. – Amasa

3

EntityFunctions è deprecato in favore di DbFunctions

public int GetNumUsersByDay(DateTime Date) 
     { 
      using (var context = db) 
      { 
       var DateDay = new DateTime(Date.Year, Date.Month, Date.Day); 
       var DateDayTomorrow = DateDay.AddDays(1); 
       return context.Users.Where(m => DbFunctions.AddHours(m.DateCreated,-5) >= DateDay && m.DateCreated < DateDayTomorrow).Count(); 
      } 
     } 
+0

... se sei in EF 6 o successivo ... –

Problemi correlati