简体   繁体   English

DateTime 参数不适用于 EF 核心查询

[英]DateTime parameter not working with EF core query

I'm working with Azure SQL Server, .net core 3.1, EF core 5.0我正在使用 Azure SQL Server、.net core 3.1、EF core 5.0

So, I have this function in my repository, which receives a datetime as parameter:所以,我的存储库中有这个函数,它接收一个日期时间作为参数:

 public IEnumerable<Channel> GetActiveChannels(DateTime date,int pageSize, int pageCounter)
        {
            try
            {
                IEnumerable<Channel> channels;

                var query = _context.Channel
                    .Include(channel => channel.ChannelStat
                    .OrderByDescending(stat => stat.RegisteredTime)
                    .Take(1))
                    .Where(channel => channel.RegisteredTime >= date)
                    .Skip(pageSize * pageCounter).Take(pageSize);
                channels = query.ToList();
                return channels;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                throw ex;
            }
        }

According to my logs, it gets correctly translated into sql as follows:根据我的日志,它被正确地转换为 sql,如下所示:

[Parameters=[@__date_0='?' (DbType = DateTime2), @__p_1='?' (DbType = Int32), @__p_2='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT [t].[YTChannelId], [t].[BannerImageUrl], [t].[Bucket], [t].[Category], [t].[CategoryId], [t].[ChannelTitle], [t].[Country], [t].[CustomUrl], [t].[Description], [t].[Engagement], [t].[Keywords], [t].[Language], [t].[LastUpdate], [t].[PublishedAt], [t].[Reach], [t].[RegisteredTime], [t].[Thumbnail], [t0].[Id], [t0].[CommentCount], [t0].[Engagement], [t0].[HiddenSubscriberCount], [t0].[Reach], [t0].[RegisteredTime], [t0].[SubscriberCount], [t0].[VideoCount], [t0].[VideoReleased], [t0].[ViewCount], [t0].[YTChannelId]
FROM (
    SELECT [c].[YTChannelId], [c].[BannerImageUrl], [c].[Bucket], [c].[Category], [c].[CategoryId], [c].[ChannelTitle], [c].[Country], [c].[CustomUrl], [c].[Description], [c].[Engagement], [c].[Keywords], [c].[Language], [c].[LastUpdate], [c].[PublishedAt], [c].[Reach], [c].[RegisteredTime], [c].[Thumbnail]
    FROM [Channel] AS [c]
    WHERE [c].[RegisteredTime] >= @__date_0
    ORDER BY (SELECT 1)
    OFFSET @__p_1 ROWS FETCH NEXT @__p_2 ROWS ONLY
) AS [t]
OUTER APPLY (
    SELECT TOP(1) [c0].[Id], [c0].[CommentCount], [c0].[Engagement], [c0].[HiddenSubscriberCount], [c0].[Reach], [c0].[RegisteredTime], [c0].[SubscriberCount], [c0].[VideoCount], [c0].[VideoReleased], [c0].[ViewCount], [c0].[YTChannelId]
    FROM [ChannelStat] AS [c0]
    WHERE [t].[YTChannelId] = [c0].[YTChannelId]
    ORDER BY [c0].[RegisteredTime] DESC
) AS [t0]
ORDER BY [t].[YTChannelId], [t0].[RegisteredTime] DESC, [t0].[Id]

where在哪里

@__date_0='2020-09-07T09:35:47.8976418Z' (DbType = DateTime2), @__p_1='0' (DbType = Int32), @__p_2='10000'

The problem is that it is returning 0 rows, when I know for a fact that there are at least 200K that fulfill the criteria.问题是当我知道至少有 200K 满足条件时,它返回了 0 行。

I don't know what to do here because I am passing a DateTime to the function, if I was passing a string I could accept that there are formatting issues.我不知道在这里做什么,因为我将 DateTime 传递给函数,如果我传递的是字符串,我可以接受存在格式问题。 But shouldn't EF core translate this date to a suitable format that will be understood by the DBMS?但是,EF 核心不应该将此日期转换为 DBMS 可以理解的合适格式吗?

Also, if I just make @__date_0='07-09-2020' with the translated sql in my management studio, it gives me the answers I expect.此外,如果我只是在我的管理工作室中使用翻译后的 sql 制作@__date_0='07-09-2020' ,它会给我我期望的答案。 So it looks like some sort of localization BS, but I still don't know how to correct it, since these dates will be generated automatically depending on when the call was made and the time part is very important to the outcome of the query.所以它看起来像是某种本地化 BS,但我仍然不知道如何更正它,因为这些日期将根据拨打电话的时间自动生成,并且时间部分对查询的结果非常重要。 Plus of course I would also like to not be tied to a specific localization config.另外,当然我也不想被绑定到特定的本地化配置。 In case it matters all dates are in UTC.万一重要,所有日期都是UTC。

Thanks in advance for the help在此先感谢您的帮助

EDIT to add the create tables requested编辑以添加请求的创建表

CREATE TABLE [dbo].[Channel](
    [YTChannelId] [nvarchar](450) NOT NULL,
    [ChannelTitle] [nvarchar](max) NOT NULL,
    [Description] [nvarchar](max) NULL,
    [CustomUrl] [nvarchar](max) NULL,
    [PublishedAt] [datetime2](7) NULL,
    [Country] [nvarchar](max) NULL,
    [BannerImageUrl] [nvarchar](max) NULL,
    [Thumbnail] [nvarchar](max) NULL,
    [Keywords] [nvarchar](max) NULL,
    [Engagement] [float] NULL,
    [Reach] [float] NULL,
    [LastUpdate] [datetime2](7) NULL,
    [Language] [nvarchar](max) NULL,
    [Bucket] [nvarchar](max) NULL,
    [RegisteredTime] [datetime2](7) NOT NULL,
    [Category] [nvarchar](max) NULL,
    [CategoryId] [nvarchar](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

CREATE TABLE [dbo].[ChannelStat](
    [Id] [uniqueidentifier] NOT NULL,
    [YTChannelId] [nvarchar](450) NULL,
    [ViewCount] [decimal](20, 0) NULL,
    [CommentCount] [decimal](20, 0) NULL,
    [SubscriberCount] [decimal](20, 0) NULL,
    [HiddenSubscriberCount] [bit] NULL,
    [VideoCount] [decimal](20, 0) NULL,
    [RegisteredTime] [datetime2](7) NOT NULL,
    [Engagement] [float] NULL,
    [Reach] [float] NULL,
    [VideoReleased] [bit] NOT NULL
) ON [PRIMARY]

EDIT to add 3 sample records编辑以添加 3 个示例记录

YTChannelId BannerImageUrl  Bucket  Category    CategoryId  ChannelTitle    Country CustomUrl   Description Engagement  Keywords    Language    LastUpdate  PublishedAt Reach   RegisteredTime  Thumbnail   Id  CommentCount    Engagement  HiddenSubscriberCount   Reach   RegisteredTime  SubscriberCount VideoCount  VideoReleased   ViewCount   YTChannelId
UC__03yLhZqBGyW2mQBtRvrQ    NULL    NULL    NULL    NULL    TBD NULL    NULL    NULL    NULL    NULL    NULL    2020-07-15 14:54:07.3633333 NULL    NULL    2020-07-15 14:54:07.3633333 NULL    3B6BF961-0E43-4824-A93F-2E1C102A8745    NULL    NULL    NULL    NULL    2020-07-15 20:35:05.9633333 NULL    NULL    0   NULL    UC__03yLhZqBGyW2mQBtRvrQ
UC__08GrddvOiUgC8_AU1FQA    NULL    NULL    NULL    NULL    TBD NULL    NULL    NULL    NULL    NULL    NULL    2020-07-15 14:59:42.9300000 NULL    NULL    2020-07-15 14:59:42.9300000 NULL    C9FD745F-6C92-4AE4-8E46-44EAD9FE8DBF    NULL    NULL    NULL    NULL    2020-07-15 20:35:05.9633333 NULL    NULL    0   NULL    UC__08GrddvOiUgC8_AU1FQA
UC__1aTDqHjrbAOHcfne7kuQ    NULL    NULL    NULL    NULL    TBD NULL    NULL    NULL    NULL    NULL    NULL    2020-07-15 15:02:59.0100000 NULL    NULL    2020-07-15 15:02:59.0100000 NULL    26F6C6D0-B545-4624-8174-B0EAE620004C    NULL    NULL    NULL    NULL    2020-07-15 20:35:05.9633333 NULL    NULL    0   NULL    UC__1aTDqHjrbAOHcfne7kuQ

EDIT to add user options编辑以添加用户选项

Set Option  Value
textsize    2147483647
language    us_english
dateformat  mdy
datefirst   7
lock_timeout    -1
quoted_identifier   SET
arithabort  SET
ansi_null_dflt_on   SET
ansi_warnings   SET
ansi_padding    SET
ansi_nulls  SET
concat_null_yields_null SET
isolation level read committed snapshot

and select GETDATE() returns 2020-09-08 11:50:27.287select GETDATE()返回2020-09-08 11:50:27.287

EDIT to add the watch screenshot编辑以添加手表屏幕截图

在此处输入图片说明

Your C# code is passing in 7th September.您的 C# 代码将于 9 月 7 日通过。 All of the data in your database is before that date - so it isn't returned.数据库中的所有数据都在该日期之前 - 因此不会返回。 Everything is working as expected.一切都按预期工作。

But why does @__date_0='07-09-2020' work then?但是为什么@__date_0='07-09-2020'起作用呢? Well, that is due to your settings - specifically dateformat mdy .嗯,这是由于您的设置 - 特别是dateformat mdy That tells SQL Server to treat that string as MDY.这告诉 SQL Server 将该字符串视为 MDY。 So you think you are passing 7th September - but you are actually passing 9th July (which "works" - since your data in 15th July is after 9th July).所以你认为你正在通过 9 月 7 日 - 但你实际上正在通过 7 月 9 日(这“有效” - 因为你在 7 月 15 日的数据在 7 月 9 日之后)。

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

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