Law*_*ker 11 c# sql sql-server nhibernate entity-framework
我正在将子系统从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();
Run Code Online (Sandbox Code Playgroud)
帐户余额类是:
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; }
}
Run Code Online (Sandbox Code Playgroud)
该表是:
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
)
)
Run Code Online (Sandbox Code Playgroud)
示例数据是(使用数字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
Run Code Online (Sandbox Code Playgroud)
该AccountBalanceByDate实体持有某一天的账户余额.如果一天没有交易,那一天将没有AccountBalanceByDate,我们应该查看前几天查看该帐户的余额.
如果我查询日期2014-02-01我应该得到:
No results
Run Code Online (Sandbox Code Playgroud)
如果我查询日期2014-02-02我应该得到:
1 | 2014-02-01 | 101 | 1390.00000
2 | 2014-02-01 | 102 | 1360.00000
3 | 2014-02-01 | 103 | 1630.00000
Run Code Online (Sandbox Code Playgroud)
如果我查询日期2014-02-03我应该得到:
1 | 2014-02-01 | 101 | 1390.00000
4 | 2014-02-02 | 102 | 1370.00000
5 | 2014-02-02 | 103 | 1700.00000
Run Code Online (Sandbox Code Playgroud)
如果我查询日期2014-02-04我应该得到:
4 | 2014-02-02 | 102 | 1370.00000
6 | 2014-02-03 | 101 | 1490.00000
7 | 2014-02-03 | 103 | 1760.00000
Run Code Online (Sandbox Code Playgroud)
如果我查询日期2014-02-05我应该得到:
7 | 2014-02-03 | 103 | 1760.00000
8 | 2014-02-04 | 101 | 1530.00000
9 | 2014-02-04 | 102 | 1540.00000
Run Code Online (Sandbox Code Playgroud)
我可以使用原始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();
}
Run Code Online (Sandbox Code Playgroud)
最好只去一次数据库,比如NHibernate和原始SQL,但只使用linq,是否可能?
更新:
修复了问题的结果.
SQL在GIST上显示示例查询:https://gist.github.com/LawfulHacker/275ec363070f2513b887
GIST上的实体框架示例:https://gist.github.com/LawfulHacker/9f7bd31a21363ee0b646
Law*_*ker 22
以下查询只需要对数据库进行一次查询即可完成所需:
var accountBalance = context
.AccountBalanceByDate
.Where(a =>
a.Date == context.AccountBalanceByDate
.Where(b => b.AccountId == a.AccountId && b.Date < date).Max(b => b.Date));
Run Code Online (Sandbox Code Playgroud)
感谢@AgentShark的帮助.
代码在GIST上:https://gist.github.com/LawfulHacker/9f7bd31a21363ee0b646