C# EF核心,按utc日期按月和按年分组

C# EF核心,按utc日期按月和按年分组,c#,asp.net-core,entity-framework-core,C#,Asp.net Core,Entity Framework Core,我将所有日期存储为UTC,并且我需要按月份和年份对实体进行分组,因此我正在执行以下操作: _dbContext.Tickets.Where(x => x.Date >= from && x.Date <= to).GroupBy(x=> new { Year = x.Date.Year, Month = x.Date.Month }).Select(x=> new

我将所有日期存储为UTC,并且我需要按月份和年份对实体进行分组,因此我正在执行以下操作:

_dbContext.Tickets.Where(x => x.Date >= from && x.Date <= to).GroupBy(x=> new {
                Year = x.Date.Year,
                Month = x.Date.Month
            }).Select(x=> new {x.Key, Count = x.Count()})

由于日期为utc,我在2020年9月1日00:30 AM创建了一张票证,但由于它存储为utc I'm+2,因此将存储为2020-08-31 22:25。现在,如果我按月份分组,我将在错误的月份将此实体分组。有没有简单的方法可以不在内存上执行此操作?

有几种方法可以引入映射到sql函数或原始sql片段的c函数

对于直接映射到同名sql函数的函数,只需定义方法

公共静态ReturnType CustomMethodArgType arg=>抛出新的NotImplementedException; 在ModelCreatingModelBuilder上受保护的覆盖无效{ builder.HasDbFunctiontypeofContext.GetMethodnameofCustomMethod; } 或者对该方法使用[DbFunction]属性

要生成像@dateattimezone@name这样的sql片段,您不能只使用SqlFunctionExpression的实例,还有一些工作要做

public static DateTimeOffset to timezone此DateTimeOffset值,字符串名称=>抛出新的NotImplementedException; 公共类SqlFragmentListExpression:SqlExpression { 公共SqlFragmentListExpressionType,RelationalTypeMapping typeMapping,参数SqlExpression[]片段:basetype,typeMapping { 碎片=碎片; } 公共SqlExpression[]片段{get;} 公共覆盖无效PrintExpressionPrinter expressionPrinter { 片段中的foreach变量f f、 印表机; } 受保护的重写表达式VisitChildrenExpressionVisitor { var frags=newsqlexpression[Fragments.Length]; var=false; forvar i=0;i{ var dto=args.ElementAt0; 返回新的SQLFragmentListExpressionTo.Type、dto.TypeMapping、, dto, 时区的新SqlFragmentExpression, args.ElementAt1; }; 然后您可以在查询中使用该方法,如

_dbContext.Tickets 其中x=>x.Date>=开始日期和新日期(&x){ 日期=x.Date.ToTimeZoneCentral欧洲标准时间 } .GroupByx=>new{ 年份=x.Date.Year, 月份=x.Date.Month }, x、 e=>新的{ x、 年, x、 月, 计数 } 应将其转换为sql

选择位于“中欧标准时间”时区的DATEPARTyear[t].[Date]作为[Year], DATEPARTmonth,[t].[Date]在“中欧标准时间”时区作为[Month], 计数*为[计数] 从[Tickets]AS[t] 按日期分组Partyear,[t].[Date]在“中欧标准时间”时区, DATEPARTmonth,[t].[Date]位于“中欧标准时间”时区
首先决定什么是错的。您想按UTC还是当地时间分组?您可以使用:x.Date.ToLocalTime>=from&&x.Date.ToLocalTime@jdweng我认为ToLocalTime不会由Linq到实体。该筛选器可以忽略,但由于从e到都是UTC,与数据库中的日期相同,因此筛选器很好,不需要。ToLocalTime。如果我可以在分组部分设置ToLocalTime,比如Month=x.Date.ToLocalTime.Month,那就可以了,但我不能,因为它将在本地进行评估@jdwengSql服务器?那么您想在时区@name生成sql日期?可能有一种方法可以定义自定义数据库函数…或定义[DbFunction]公共静态DateTimeOffset SWITCHOFFSET DateTimeOffset值、字符串时区,我将在接下来的几天里尝试这一点,我将带着反馈回来。谢谢你的解释,这似乎是个好办法。!我尝试了这个解决方案,但它有一个问题,如果您使用在时区转换,它只会在末尾添加小时数,但是如果您尝试选择月份,它仍然会选择错误的月份。可以使用2020-08-01 00:30:00.0000000作为日期进行测试,该日期应翻译为2020-07-31 22:30:00.0000000,但时区返回2020-08-01 00:30:00.0000000+02:00。我不得不修改ToTimeZone方法以使用Datetime而不是DateTimeOffset,因为我现在使用的是这种类型