我有一个MVC控制器操作,该操作以这种方式进行数据库查询:
var marcaciones = db.Marcacion
其中db是Entity Framework中的数据库上下文,而Marcacion是数据库表。该指令之后,marcaciones
类型变为
System.Data.Entity.DbSet`1[CasinosCloud.Models.Marcacion]
这允许在框架实际在数据库中执行查询之前添加任何过滤器。
到目前为止,很好。
但是,根据特定条件,marcaciones
变量是以不同的方式分配的。
数据库模型使得数据库中的marcaciones
实体是另一个实体的子代。要获得该marcaciones
列表,我可以这样做:
var marcaciones = trabajador.ServicioSupervisado.SelectMany(s => s.Marcacion).AsQueryable();
从上面的说明可以推断,trabajador
是具有许多ServicioSupervisado
实体的父数据库实体,而这些实体又可以具有许多Marcacion
实体。
由于marcaciones
变量与我之前显示的marcaciones
变量相同,因此我必须转换为Queryable
。
执行上述指令后,marcaciones
类型变为;
{System.Linq.Enumerable+<SelectManyIterator>d__17`2
[CasinosCloud.Models.Servicio,CasinosCloud.Models.Marcacion]}
这意味着查询实际上已转换为可枚举列表。
在不应用其他过滤器的情况下,所有方法均有效。当我添加查询过滤器时,我遇到了第二种形式的问题。首先,整个网页速度较慢,因为所有筛选器都应用在内存列表中,而不是数据库中,其次,字符串比较存在问题,特别是当数据库中的文件以大写形式存储时,我试图以小写形式查找文本。当然,在这种情况下什么也找不到。
我认为通过解决类型问题可以减少问题。为什么在调用SelectMany
之后实际上执行查询并将其转换为可枚举列表?有没有办法避免这种情况以及所有在数据库中执行的情况?也许我应该不使用SelectMany
来重写该指令。我尝试使用db.Marcacion.Insersect()
与此代码进行交集,但是出现相同的问题:
trabajador.ServicioSupervisado.SelectMany(s => s.Marcacion)
编辑:
我要在数据库中执行的查询采用以下形式:
第一种方式:
SELECT m.*
FROM Marcacion m
第二种方式:
SELECT m.*
FROM Marcacion m
INNER JOIN Servicio s ON s.ServicioId = m.ServicioId
INNER JOIN Trabajador t ON t.TrabajadorId = s.TrabajadorId
WHERE t.TrabajadorId = 1069
编辑2:
第二种方式,我尝试了:
marcaciones = marcaciones.Where(m => trabajador.ServicioSupervisado.Any(s => s.ServicioId == m.ServicioId));
此后,当在数据库中实际执行查询时,会发生此错误:
System.NotSupportedException:'无法创建类型为'CasinosCloud.Models.Servicio'的常量值。在这种情况下,仅支持原始类型或枚举类型。'
答案 0 :(得分:-1)
我通过这样编写查询来解决它:
var servicios = trabajador.ServicioSupervisado.Select(s => s.ServicioId);
marcaciones = marcaciones.Where(m => servicios.Any(s => s == m.ServicioId));
这种方式在我调用ToList()
时执行查询,并且在我提到的两种情况下都有效,因为查询直接在应用了所有过滤器的数据库中运行,所以在这两种情况下都非常快。
通过查看数据库日志,实体框架执行的最终查询为:
SELECT
[Extent1].[MarcacionId] AS [MarcacionId],
[Extent1].[MonitorId] AS [MonitorId],
[Extent1].[TrabajadorId] AS [TrabajadorId],
[Extent1].[EmpresaId] AS [EmpresaId],
[Extent1].[ServicioId] AS [ServicioId],
[Extent1].[MarcacionFechaHora] AS [MarcacionFechaHora],
[Extent1].[MarcacionEntradaSalida] AS [MarcacionEntradaSalida],
[Extent1].[MarcacionChecksum] AS [MarcacionChecksum],
[Extent1].[MarcacionEquipo] AS [MarcacionEquipo],
[Extent1].[MarcacionEsManual] AS [MarcacionEsManual],
[Extent1].[MarcacionCreadoEn] AS [MarcacionCreadoEn],
[Extent1].[MarcacionActualizadoEn] AS [MarcacionActualizadoEn],
[Extent1].[MarcacionIndice] AS [MarcacionIndice]
FROM [dbo].[Marcacion] AS [Extent1]
INNER JOIN [dbo].[Trabajador] AS [Extent2] ON [Extent1].[TrabajadorId] = [Extent2].[TrabajadorId]
WHERE ( EXISTS (SELECT
1 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
WHERE 3 = [Extent1].[ServicioId]
)) AND ([Extent2].[TrabajadorNombres] + N' ' + [Extent2].[TrabajadorApellidos] LIKE @p__linq__0 ESCAPE N'~') AND ([Extent1].[MarcacionFechaHora] >= @p__linq__1) AND ([Extent1].[MarcacionFechaHora] <= @p__linq__2)