5
var res = Context.Exampletable
                 .Where(s => s.CompanyId == CompanyId &&  
                             Convert.ToDateTime(s.TextDate) >= DateTime.Now)
                 .Select(x => new Exampletable { TextDate = x.TextDate })
                 .FirstOrDefault();

这是我的问题陈述之一的 Linq。我想从当前日期和时间戳中获取记录未来的日期记录,所以我正在对其进行转换和比较,Datetime但我得到了这个错误:

无法翻译LINQ 表达式 'DbSet
.Where(a => Convert.ToDateTime(a.TextDate) > Convert.ToDateTime(DateTime.Now))' >。以可翻译的形式重写查询,或通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估

注意:在 Postgresql DBTextDate列中具有字符串数据类型并包含诸如“4/1/2020 10:00 AM”之类的值。

请为此提供解决方案。

4

3 回答 3

3

如果您真的无法更改基础列类型,那么请Convert.ToDateTime使用映射到 PostgreSQLCAST运算符的 C# 强制转换运算符,而不是不受支持:

(DateTime)(object)s.TextDate >= DateTime.Now

请注意,object为了使 C# 编译器满意,需要“中间”转换。


PS我真的不知道为什么支持某些类似的方法ConvertToInt32而其他类似ToDateTime的方法不支持。我猜这只是另一个 EF Core 不一致。

于 2020-04-01T14:57:49.327 回答
1

人们决定将 DateTime 值存储为字符串,然后命令数据库的用户使用这些值进行计算,这总是让我感到困惑。我可以想象你想诅咒决定这样做的人,特别是因为他决定以这种不可排序的方式存储它。

最佳解决方案

如果可能,请更改数据库以将 DateTimes 存储为 DateTimes,或者如果您的数据库语言不知道如何执行此操作,请将 DateTimes 的 Ticks 存储为 longs。数据库的未来用户将荣耀您的名字!

long nowTicks = DateTime.Now.Ticks;
var result = Context.Exampletable
    .Where(example => example.CompanyId == CompanyId && example.DateTicks >= nowTicks);

几乎是最佳解决方案

如果将 DateTimes 保存为字符串的决定是 PostgreSQL 开发人员的决定,那么尝试查找他们是否具有处理这些日期时间的函数,尤其是比较

“情况越来越糟”的解决方案

尝试找出 PostgreSQL 是否具有字符串操作功能,以便您可以将 4/1/2020 10:00 AM 转换为 IComparable。如果您想编写代码来将此值与例如 2019 年 4 月 1 日上午 10:00 或 2020 年 4 月 2 日上午 10:00 进行比较是很困难的,所以我想这将是一项艰巨的工作在 SQL 中

于 2020-04-01T12:07:55.777 回答
0

使用 EF Core 5+,您可以使用 ValueConverters 作为此方案的“解决方法”,并使用内置的 StringDateTimeConverter ( https://apisof.net/catalog/e0dd77d4-73c3-6bba-e51a-4842a59894d1 )。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Exampletable>()
        .Property(e => e.TextDate)
        .HasConversion<string>();
}

public class ExampleTable
{
 public DateTime TextDate {get; set;}
}

然后简单

DateTimeOffset someValue = some-value-here;
var query = DbContext.Entities.Where(e => e.TextDate <= someValue);

重要的是,您的 LINQ 查询中的参数是 datetimeoffset ,因为如果您不这样做,EF CORE 不会为该列生成带有 CAST 操作的 SQL。有关示例,请参见此处https://gist.github.com/dasiths/19b885c58442226d9fc8b89bc78511e4

生成的 SQL 会像

((@__startSearch_0 >= CAST([s].[TextDate]) AS datetimeoffset))

编辑:重申一下,在这里使用值转换器是一种“解决方法”。要查看对选项的完整分析,我在此处https://dasith.me/2022/01/23/ef-core-datetime-conversion使用值转换器 hack 编写了对“变通办法”的完整详细分析-兔子洞/

于 2022-01-22T16:06:54.310 回答