实体框架6相关实体,其中datetime子句未转换为SQL

时间:2018-08-23 13:15:04

标签: c# entity-framework-6

如何在不访问数据库上下文的情况下将日期过滤器添加到生成的SQL查询中?

EF进行一些非常昂贵的查询。我不会将结果强制转换为IEnumerable或将其用作IEnumerable,所以我希望EF能够进行有效的查询。我希望它使用开始和停止时间来过滤SQL中的结果。

EF翻译了以下内容

SELECT TOP (1) 
    [Extent1].[Channel_ID] AS [Channel_ID], 
    [Extent1].[ChannelType_ID] AS [ChannelType_ID], 
    [Extent1].[Name] AS [Name], 
    FROM [dbo].[Channel] AS [Extent1]
    WHERE [Extent1].[Channel_ID] = @p__linq__0
p__linq__0: '1' (Type = Int32, IsNullable = false)

SELECT 
    [Extent1].[Channel_ID] AS [Channel_ID], 
    [Extent1].[ValueTime] AS [ValueTime], 
    [Extent1].[Value] AS [Value]
    FROM [dbo].[ChannelValue] AS [Extent1]
    WHERE [Extent1].[Channel_ID] = @EntityKeyValue1
EntityKeyValue1: '1' (Type = Int32, IsNullable = false)

进入

context.ChannelValues
.Where(cv => cv.Channel_ID == id && start < cv.ValueTime && cv.ValueTime <= stop);

我很满意的第一个SQL查询,但是第二个应该创建类似于以下内容的查询

SELECT 
    [Extent1].[Channel_ID] AS [Channel_ID], 
    [Extent1].[ValueTime] AS [ValueTime], 
    [Extent1].[Value] AS [Value]
    FROM [dbo].[ChannelValue] AS [Extent1]
    WHERE ([Extent1].[Channel_ID] = @p__linq__0) AND (@p__linq__1 < [Extent1].[ValueTime]) AND ([Extent1].[ValueTime] <= @p__linq__2)
p__linq__0: '1' (Type = Int32, IsNullable = false)
p__linq__1: '7/1/2018 12:00:00 AM' (Type = DateTime2, IsNullable = false)
p__linq__2: '7/23/2018 11:45:00 AM' (Type = DateTime2, IsNullable = false

它导致

EXEC sp_msforeachdb 
'if exists(select 1 from [?].sys.objects where name=''YourProcHere'')
select ''?'' as DbName from [?].sys.objects where name=''YourProcHere'''

在实际需要的地方,我无权访问DatabaseContext。

2 个答案:

答案 0 :(得分:1)

我认为查询的第二部分根本没有传递给SQL。

这告诉SQL返回Channel_ID等于id的所有ChannelValues。

context.Channels
  .First(ch => ch.Channel_ID == id)
  .ChannelValues

然后在内存中执行第二个where子句。

.Where(cv => start < cv.ValueTime && cv.ValueTime <= stop);

要在数据库中执行所有这些操作,您将需要执行以下操作:

context.Channels
  .Where(ch => ch.Channel_ID == id)
  .SelectMany(x => x.ChannelValues)
  .Where(cv => start < cv.ValueTime && cv.ValueTime <= stop)

虽然我不知道这是否回答您是否在不访问数据库上下文的情况下如何做到这一点

答案 1 :(得分:0)

“ EF会进行一些非常昂贵的查询”,如果您知道有什么不好的地方,但仍然以这种方式(不是EF错误)进行操作,则可以控制如何使用具有局限性的框架*。

您可以完全按照自己的方式来做。

即如果您使用原始sql执行此操作,该怎么做。

然后只需在EF中执行相同操作即可。

var channel = context.Channels.First(x=> x.Channel_ID == id)
channel.ChannelValues = context.ChannelValues.Where(x => x.Channel_ID == id 
                                             && start < x.ValueTime 
                                             && x.ValueTime <= stop
                              ).ToList();