【发布时间】:2020-09-02 03:17:45
【问题描述】:
我正在开发一个酒店领域应用程序 (.Net Core 2.2),我正在其中开发一个报告模块。在仪表板中,有几个过滤器可用于从数据库中获取记录。
下面是我用来包含过滤器的 DTO
public class SearchDto
{
public DateTime DateForm {get;set;}
public DateTime DateTo {get;set;}
public DateSearchType SearchType {get;set;}
public string RegionId {get;set;}
public OrdersStatus status {get;set;}
public string PaymentModeTypes {get;set;}
public string channel {get;set;}
}
这里 DateSearchType 是一个有值的枚举
- 开始 // 服务开始日期
- 结束 // 服务结束日期
- 创建 // 订单创建日期
还有 OrdersStatus(一个枚举),其值包括 All 、 Confirmed 、 Canceled 、 PaymnetFailed 等
PaymentModeTypes 可以是单个字符串或逗号分隔的字符串,例如:“NetBanking、CreditCard、DebitCard、Cash”
RegionId 也是单个字符串或逗号分隔的字符串,如 "101, 102, 102"
“网络”或“网络、移动”频道相同
我目前使用的ef核心表达如下
var v = Database.Orders.List(
x => ((SearchType == DateSearchType.Start) ? x.Services.Any(y => (y.MinStartTime >= DateForm.Date && y.MinStartTime <= DateTo.Date)) || DateForm.Date.Equals(DateTime.MinValue) : true)
&& ((SearchType == DateSearchType.End) ? x.Services.Any(y => y.MaxEndTime >= DateForm.Date && y.MaxEndTime <= DateTo.Date) : true)
&& ((SearchType == DateSearchType.Creation) ? x.BookingDate.Date >= DateForm.Date && x.BookingDate.Date <= DateTo.Date : true)
&& (RegionId.Length == 0 || RegionId.Contains(x.RegionId))
&& (status == OrdersStatus.All || x.Status == status)
&& (string.IsNullOrEmpty(PaymentModeTypes) || PaymentTypes.Contains(x.PaymentType))
&& (string.IsNullOrEmpty(channel) || channels.Contains(x.ChannelName)), //Where
x => x.Guests,
x => x.Services
);
这里的 Guest 和 Services 是在 Orders 模型中设置为导航属性的另外两个表
这个表达式工作正常,但执行时间太长,有什么好的方法来优化它或重写这段代码的正确方法吗?
如果没有提供任何过滤器的值,排除过滤器的最佳做法是什么。
很少有过滤器不是强制性的,可以提供也可以不提供,因此查询执行必须是动态的。未提供过滤器值时的当前实现
&& (string.IsNullOrEmpty(PaymentModeTypes) || PaymentTypes.Contains(x.PaymentType))
任何人都可以建议一些好的材料或任何关于此的代码,以便我可以优化它。
请忽略错字,因为我不习惯使用深色主题
编辑 1:客户端评估设置为关闭
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
}
【问题讨论】:
-
过滤器是转换成 SQL 还是在内存中求值?
-
它在 MySql 数据库上运行,而不是在内存集合中
-
没错,但您使用的是支持所谓的“客户端评估”的 EF Core 2.x。因此,为了确保过滤发生在数据库中,请关闭客户端评估,如下所示docs.microsoft.com/en-us/ef/core/querying/…。这是首先要检查的。请先确认一下,然后我们可以考虑查询是否可以优化。
-
它没有在我的数据库上下文中配置,所以我猜默认情况下它是打开的,将它设置为关闭参见编辑 1:
-
你好@IvanStoev 现在有什么建议吗?
标签: c# entity-framework-core mysql-workbench .net-core-2.2