简体   繁体   English

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

[英]Entity Framework 6 related entity where datetime clause doesn't translate to SQL

How do I get the date filter into the generated SQL query without access to database context? 如何在不访问数据库上下文的情况下将日期过滤器放入生成的SQL查询中?

EF makes some very expensive queries. EF进行一些非常昂贵的查询。 I don't cast or use the results as IEnumerable, so I would expect EF to make an efficient query. 我不会将结果强制转换为IEnumerable或将其用作IEnumerable,所以我希望EF能够进行有效的查询。 I would expect it to use the start and stop times to filter the results in SQL. 我希望它使用开始和停止时间来过滤SQL中的结果。

EF translates the following EF翻译了以下内容

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

into

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)

The first SQL query I'm happy with, but the second should create a query similar to what the following does 我很满意的第一个SQL查询,但是第二个应该创建类似于以下内容的查询

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

it results in 它导致

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

Where I actually need this I don't have access to the the DatabaseContext. 在我实际需要的地方,我无权访问DatabaseContext。

I don't think the second part of the query is getting passed to the SQL at all. 我认为查询的第二部分根本没有传递给SQL。

This tells SQL to return all the ChannelValues with the Channel_ID equal to id. 这告诉SQL返回Channel_ID等于id的所有ChannelValues。

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

The second where clause is then executed in memory. 然后在内存中执行第二个where子句。

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

To execute all of this in the database you will need to do something like this: 要在数据库中执行所有这些操作,您将需要执行以下操作:

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

Though I don't know if this answers you question how to do this without access to the database context 虽然我不知道这是否回答您是否在不访问数据库上下文的情况下如何做到这一点

"EF makes some very expensive queries" mmm you have control of how you would like to use the framework with its limitation*, if you know something is bad but still do it that way its not EF fault. “ EF进行一些非常昂贵的查询”,如果您知道有什么不好的地方,但仍然以这种方式(不是EF错误)进行操作,则可以控制如何使用具有局限性的框架*。

You could do it exactly the way you have. 您可以完全按照自己的方式来做。

ie if you did this with raw sql how would you do it. 即,如果您使用原始sql执行此操作,您将如何做。

Then simply do the same in EF. 然后只需在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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM