当前位置: 首页 > 面试题库 >

实体框架的子查询

冀嘉木
2023-03-14
问题内容

我正在将子系统从 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



 类似资料:
  • 实体框架5.0首先使用现有数据库编写代码。使用电动工具对类进行逆向工程。一切都很好。数据库有两个表。一个父母和一个孩子的外键返回到父母ID。ID都是带有自动增量的int。我添加了许多父母记录,现在想将孩子记录添加到特定的父母。我能看到的唯一方法是通过在父母表中搜索名称或其他属性并返回ID来找到适当的父母ID。然后在添加孩子时在外键属性中使用该ID。我不想设置新父母,所以这是将孩子添加到现有父母的唯

  • 我有一个表存储3K条记录, 我对实体框架和ORM是个新手,但我能理解出了问题。 运行此linq查询时: 我在mysql端得到以下查询: 执行此查询大约需要3.50秒。 说明此查询: 当我查询: 我只有0.01秒... 跑着再解释一遍我得到: 我不明白为什么会这样。 Entity Framework 4.3 MySQL Connector Net 6.5.4.0 tcms_articles: 那么为

  • 在我们的生产环境中,我们有一个自动部署脚本,可以关闭站点,运行迁移,然后使其重新联机。我们希望在不需要运行任何迁移的情况下,通过切换到新代码来避免关闭站点。 实体框架是否有像“更新数据库”这样的命令,允许我们检查是否有迁移要运行?

  • 问题内容: 我需要在每个用户已经有一个ID作为键的数据库中存储大量用户数据。但是,这些用户全部来自更大的用户池,因此,该ID不会增加并且无法自动生成。我需要能够手动设置ID。 是否有捷径可寻? 问题答案: 我进行了一些测试,这似乎对我在EF 7.0.0 rc1-final上有效: 我的测试代码: (完整的程序代码在这里:http : //pastebin.com/hSs9HZCP) 它可以正确插入

  • 如何模拟AsNoTracking方法? 在下面的示例中,DbContext已经注入到服务类中,如果我从GetOrderedProducts方法中移除AsNoTracking扩展方法,它可以正常工作,但是with AsNoTracking测试失败,因为它返回null。我还试图模拟AsNoTracking以返回正确的值,但它不起作用。

  • 问题内容: 使用实体框架返回人名列表,其中人名包含字符串数组中的文本。 比方说: 和查询 这将编译并运行,但是该过程实际上是从数据库中调用所有记录,然后对返回的数据执行我的where子句。这是有道理的。 有没有一种方法可以重写查询,以便在SQL中生成where子句? 问题答案: 我假设dataContext.People是来自的,并且不涉及实现的指令,例如或。 答案在这里:http : //www