我正在将子系统从 NHibernate 移植到 Entity Framework, 并希望看到将以下查询移植到 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();
帐户余额类别为:
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; } }
该表是:
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 ) )
示例数据是(使用数字ID可以更好地理解):
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
该 AccountBalanceByDate 实体持有某一天的账户余额。如果某天没有交易,则该天将没有 AccountBalanceByDate ,我们应该查看前几天以查看该帐户的余额。
如果我查询日期为 2014-02-01, 我应该得到:
No results
如果我查询日期为 2014-02-02, 我应该得到:
1 | 2014-02-01 | 101 | 1390.00000 2 | 2014-02-01 | 102 | 1360.00000 3 | 2014-02-01 | 103 | 1630.00000
如果我查询日期为 2014-02-03, 我应该得到:
1 | 2014-02-01 | 101 | 1390.00000 4 | 2014-02-02 | 102 | 1370.00000 5 | 2014-02-02 | 103 | 1700.00000
如果我查询日期为 2014-02-04, 我应该得到:
4 | 2014-02-02 | 102 | 1370.00000 6 | 2014-02-03 | 101 | 1490.00000 7 | 2014-02-03 | 103 | 1760.00000
如果我查询日期为 2014-02-05, 我应该得到:
7 | 2014-02-03 | 103 | 1760.00000 8 | 2014-02-04 | 101 | 1530.00000 9 | 2014-02-04 | 102 | 1540.00000
我可以使用原始SQL在Entity Framework中执行此操作,但这并不理想。
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(); }
最好只一次访问数据库,就像在 NHibernate 和原始SQL中一样,但是仅使用 linq ,有可能吗?
以下查询仅需对数据库执行一次查询即可完全满足我的需要:
var accountBalance = context .AccountBalanceByDate .Where(a => a.Date == context.AccountBalanceByDate .Where(b => b.AccountId == a.AccountId && b.Date < date).Max(b => b.Date));
感谢@AgentShark的帮助。
该代码在GIST上:https : //gist.github.com/sergiogarciadev/9f7bd31a21363ee0b646