Sous-requête avec Entity Framework

Je porte un sous-système de NHibernate à Entity Framework et je veux voir la meilleure façon de porter la requête suivante vers EF .

var date = DateTime.Now; // It can be any day AccountBalanceByDate abbd = null; var lastBalanceDateByAccountQuery = QueryOver.Of<AccountBalanceByDate>() .Where(x => x.AccountId == abbd.AccountId && x.Date < date) .Select(Projections.Max<AccountBalanceByDate>(x => x.Date)); var lastBalances = session.QueryOver<AccountBalanceByDate>(() => abbd) .WithSubquery.WhereProperty(x => x.Date).Eq(lastBalanceDateByAccountQuery) .List(); 

La class de solde du count est:

 public class AccountBalanceByDate { public virtual int Id { get; set; } public virtual int AccountId { get; set; } public virtual DateTime Date { get; set; } public virtual decimal Balance { get; set; } } 

La table est:

 CREATE TABLE [dbo].[AccountBalanceByDate] ( [Id] int NOT NULL, [AccountId] int NOT NULL, [Date] [datetime] NOT NULL, [Balance] [decimal](19, 5) NOT NULL, PRIMARY KEY CLUSTERED ( [Id] ASC ) ) 

Un exemple de données est (en utilisant des identifiants numériques pour une meilleure compréhension):

 Id | Date | Account | Balance ------------------------------------ 1 | 2014-02-01 | 101 | 1390.00000 2 | 2014-02-01 | 102 | 1360.00000 3 | 2014-02-01 | 103 | 1630.00000 4 | 2014-02-02 | 102 | 1370.00000 5 | 2014-02-02 | 103 | 1700.00000 6 | 2014-02-03 | 101 | 1490.00000 7 | 2014-02-03 | 103 | 1760.00000 8 | 2014-02-04 | 101 | 1530.00000 9 | 2014-02-04 | 102 | 1540.00000 

L'entité AccountBalanceByDate détient le solde du count dans un jour spécifique. Si un jour n'a pas de transaction, ce jour n'aura pas de AccountBalanceByDate et nous devrions searchr les jours précédents pour voir le solde de ce count.

Si je request à la date 2014-02-01 je devrais get:

  No results 

Si je request à la date 2014-02-02 je devrais get:

  1 | 2014-02-01 | 101 | 1390.00000 2 | 2014-02-01 | 102 | 1360.00000 3 | 2014-02-01 | 103 | 1630.00000 

Si je request à la date 2014-02-03 je devrais get:

  1 | 2014-02-01 | 101 | 1390.00000 4 | 2014-02-02 | 102 | 1370.00000 5 | 2014-02-02 | 103 | 1700.00000 

Si je request avec la date 2014-02-04 je devrais get:

  4 | 2014-02-02 | 102 | 1370.00000 6 | 2014-02-03 | 101 | 1490.00000 7 | 2014-02-03 | 103 | 1760.00000 

Si je request à la date 2014-02-05 je devrais get:

  7 | 2014-02-03 | 103 | 1760.00000 8 | 2014-02-04 | 101 | 1530.00000 9 | 2014-02-04 | 102 | 1540.00000 

Je peux le faire dans Entity Framework en utilisant du SQL brut, mais ce n'est pas l'idéal.

 using (var context = new DbContext()) { var lastBalances = context.AccountBalanceByDate.SqlQuery( @"SELECT * FROM [AccountBalanceByDate] AB WHERE DATE = ( SELECT MAX(Date) FROM [AccountBalanceByDate] WHERE AccountId = AB.AccountId AND DATE < @p0 )", date).ToList(); } 

Il est préférable d'aller à la database une seule fois, comme dans NHibernate et SQL brut, mais en utilisant juste linq , est-ce possible?

METTRE À JOUR:

Résultats corrigés dans la question.

SQL montrant l'exemple de requête sur GIST: https://gist.github.com/LawfulHacker/275ec363070f2513b887

Échantillon Entity Framework sur GIST: https://gist.github.com/LawfulHacker/9f7bd31a21363ee0b646

La requête suivante fait exactement ce dont j'ai besoin avec une seule requête à la database:

 var accountBalance = context .AccountBalanceByDate .Where(a => a.Date == context.AccountBalanceByDate .Where(b => b.AccountId == a.AccountId && b.Date < date).Max(b => b.Date)); 

Merci @AgentShark pour l'aide.

Le code est sur GIST: https://gist.github.com/LawfulHacker/9f7bd31a21363ee0b646

Enfin, une solution. 🙂

 var date = DateTime.Now; // It can be any day var lastBalances = (from a in context.AccountBalanceByDate where a.Date < date group a by new {a.AccountId} into g select g.OrderByDescending(a => a.Date).FirstOrDefault() into r select new { Id = r.Id, AccountId = r.AccountId, Date = r.Date, Balance = r.Balance }).ToList(); 

Vous le vouliez dans LINQ, mais personnellement, je pourrais garder le SQL pour la maintenabilité.