实体框架的子查询 [英] Subquery with Entity Framework

查看:104
本文介绍了实体框架的子查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要将子系统从 NHibernate 移植到 Entity Framework ,并希望了解将以下查询移植到 EF 的最佳方法.

I'm porting a subsystem from NHibernate to Entity Framework and want to see the best way to port the following query to 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以便更好地理解):

A sample data is (using numeric ids for better understanding):

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 ,我们应该查找前几天以查看该帐户的余额.

The AccountBalanceByDate entity hold the account balance in a specific day. If a day doesn't have a transaction, that day will not have an AccountBalanceByDate and we should look for the previous days to see the balance for that account.

如果我查询日期为 2014-02-01 ,我应该得到:

If I query with the date 2014-02-01 I should get:

 No results

如果我查询日期为 2014-02-02 ,我应该得到:

If I query with the date 2014-02-02 I should get:

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

如果我查询日期为 2014-02-03 ,我应该得到:

If I query with the date 2014-02-03 I should get:

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

如果我查询日期为 2014-02-04 ,我应该得到:

If I query with the date 2014-02-04 I should get:

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

如果我查询日期为 2014-02-05 ,我应该得到:

If I query with the date 2014-02-05 I should get:

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

我可以使用原始SQL在Entity Framework中执行此操作,但这并不理想.

I can do this in Entity Framework using raw SQL, but it is not the ideal.

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 ,有可能吗?

It is preferred to go to database just one time, like in NHibernate and raw SQL, but using just linq, is it possible?

更新:

修正问题后的结果.

SQL显示有关GIST的示例查询: https://gist.github.com/LawfulHacker/275ec363070f2513b887

SQL showing the sample query on GIST: https://gist.github.com/LawfulHacker/275ec363070f2513b887

GIST上的实体框架示例: https://gist.github.com/LawfulHacker/9f7bd31a21363ee0b646

Entity Framework sample on GIST: https://gist.github.com/LawfulHacker/9f7bd31a21363ee0b646

推荐答案

以下查询仅对数据库执行一次查询即可完全满足我的需要:

The following query do exactly what I need with just one query to the database:

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

感谢@AgentShark的帮助.

Thanks @AgentShark for the help.

代码在GIST上: https://gist.github.com/LawfulHacker/9f7bd31a21363ee0b646

这篇关于实体框架的子查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆