【问题标题】:Is it OK to do many database round trips in one controller action在一个控制器操作中进行多次数据库往返是否可以
【发布时间】:2018-01-01 00:21:26
【问题描述】:

我正在编写一个网络应用程序,它有一个管理仪表板,并且有一个数据库中所有数据的摘要

这里正在使用 MSSql。

有没有办法在一轮调用中从不同的表中获取所有这些数据?

我还担心我的存储库设计。我返回一个 IQueryable,因为将所有数据作为 IEnumerable 在内存中获取并使用扩展方法在中间执行更多过滤/分页绝对不会有效。

有没有更好的方法来制作我的存储库?

这是我的 ViewComponent 动作(也可以是控制器动作):

public async Task<IViewComponentResult> InvokeAsync()
    {
        var agents = _repository.AgentData.GetAll();
        var applications = _repository.ApplicationData.GetAll();
        var paymentRequests = _repository.PaymentRequestData.GetAll();

        var universityCommissionCalcuator = new CommissionUniversityCalculator(0);
        var commissionCalcuator = new CommissionReferralCalculator(universityCommissionCalcuator);
        var commission = await _repository.AgentData.GetTotalCommissions(applications, commissionCalcuator);

        var result = AdminSummaryMapper.ToViewModel(agents, applications, paymentRequests, commission);

        return View(result);
    }

AdminSummaryMapper:

public static class AdminSummaryMapper
{
    public static AdminSummaryViewModel ToViewModel(IQueryable<Agent> agents, 
                                                    IQueryable<Application> applications, 
                                                    IQueryable<PaymentRequest> paymentRequests,
                                                    Commission commission)
    {
        var result = new AdminSummaryViewModel()
        {
            TotalStudents = applications.Count(),
            ConfirmedStudents = applications.Count(app => app.ApplicationStatus == ApplicationStatus.Confirmed),
            UnderEvaluationStudents = applications.Count(app => app.ApplicationStatus == ApplicationStatus.UnderEvaluation),
            TotalAgents = agents.Count(),
            PaymentRequests = paymentRequests.Count(),
            TotalCommission = commission.TotalComission,
            NetCommission = commission.NetComission,
        };

        return result;
    }
}

【问题讨论】:

  • 在您的存储库中引入一种方法,该方法返回指定页面的 IEnumerable 中的所有数据。使用 EF 以最少的往返次数获取所有数据。进行性能测试,如果性能足以满足您的需求,那么您就完成了。如果没有,请将工作推送到存储过程并再次进行性能测试。如果不够快,分析执行计划,找出瓶颈。使用分页。不要做任何过早的优化。
  • 非常明智的方法,我实际上已经尝试将分页添加到我的存储库中,但结果证明这是一个糟糕的选择,因为我需要在分页之前进行过滤......所以基本上分页应该扩展一个 IQueryable .

标签: c# design-patterns asp.net-core entity-framework-core


【解决方案1】:

您没有提到您在 EF 中使用哪种类型的数据库(SQLServer、MySql、Oracle,...)。

使用 SQL 从关系数据库中检索聚合数据是一项非常简单的工作。您可以定义一个视图并使用像这里这样的子选择:https://www.essentialsql.com/get-ready-to-learn-sql-server-19-introduction-to-sub-queries/

【讨论】:

  • 我正在使用 MSSql... 在我的问题中添加了这一点,谢谢!
  • 对不起。我一定错过了。
【解决方案2】:

如果您需要进行多次调用,因为数据来自不同的地方并且无法在单个数据库查询中请求,那么这不是问题。在有意义的地方进行优化和缓存。

【讨论】:

  • “优化和缓存”如何?
  • 您可以查看您的查询并在可能的情况下包含单个查询,并且您可以通过在特定时间段内(例如在会话中)存储结果来缓存,以减少到数据库的往返行程。您需要查找可用的缓存技术。
  • 会话 != 缓存。请不要为此类事情推荐会话。 ASP.NET Core 具有您可以使用的实际缓存基础架构,因此请使用它。
  • 同意,“您需要查找可用的缓存技术”
【解决方案3】:

传统上,如果您想从一次往返中获取大量数据,SQL Server 的答案是存储过程。实体框架可能有一种直接访问存储过程的方法,但是按照您的格式,可以从这样一个存储过程在数据库上构建一个视图,该存储过程从多个查询中提取数据,因此每个查询都在服务器端执行,然后是结果一口气被拉回来。

直接访问存储过程:

http://www.entityframeworktutorial.net/stored-procedure-in-entity-framework.aspx

How to call Stored Procedure in Entity Framework 6 (Code-First)?

这要求存储过程对数据进行操作,使其返回到一个表中。 Entity Framework 确实不是做到这一点的最佳方法,真正的目的是在添加自动完成功能的同时,在没有 WHERE 子句的情况下让执行新手错误(例如 UPDATE 和 DELETE)变得更加困难。

【讨论】:

  • 听起来像是添加了另一个在一次调用中执行此类操作的存储库,对吧?
  • 基本上。但如果您使用的是 MS SQL Server,则无需安装任何内容。打开 Management Studio,您可以在那里创建视图或过程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 2016-07-10
  • 1970-01-01
相关资源
最近更新 更多