【问题标题】:Convert string time to datetime or timespan in entity framework query在实体框架查询中将字符串时间转换为日期时间或时间跨度
【发布时间】:2023-03-16 15:46:09
【问题描述】:

我已经在数据库中存储了时间字符串"12:20 PM",我想将它与 linq 查询 (EF) 中的当前时间进行比较。因为我不能使用 Convert.ToDateTime 等转换它,因为它不能转换成任何 sql 表达式。

我正在考虑编写如下查询,但我知道这无济于事。请指教。

List<CompanyScheduler> companySchedulers = 
    context.CompanySchedulers
          .Where(m => m.IsActive && m.Start <= EntityFunctions.AddMinutes(td, m.TimeZoneOffset))
          .Where(m => (m.LastRun.HasValue && EntityFunctions.TruncateTime(m.LastRun) < tdExcludeTime) || (!m.LastRun.HasValue))
          .Where(m => (m.When == (int)When.Daily && (Convert.ToDateTime("01-01-1990 " + m.RecurAt).TimeOfDay < EntityFunctions.AddMinutes(td, m.TimeZoneOffset).Value.TimeOfDay)) ||
                      (m.When == (int)When.Once && !m.LastRun.HasValue) ||
                      (m.When == (int)When.Weekly && m.RecurrEvery.Contains(today)))
          .ToList();

【问题讨论】:

  • 您最好添加一列,然后使用 SQL 以合理且类型安全的方式更新该列。
  • @Aron:我没明白。请多解释一下。
  • 您的主要问题是您在数据库中将时间存储为varchar。这与您存储的信息不匹配。因此,您想使用Convert.ToDateTime 来解决此问题。正确的方法是首先将其存储为日期时间。这就是数据库模式的全部意义所在。修复您的架构,使其保持理智,然后您的查询将很容易。
  • @Aron 好的,如果我更改数据库架构,那么在 EF 查询中比较时间部分的查询应该是什么? (我们不能在 EF 查询中使用 Convert.ToDateTime。)
  • 从 EF 5 开始,支持Time 的数据类型,映射到System.TimeSpan。鉴于TimeSpan startTime;,所以很简单.Where(m =&gt; m.Start &lt; startTime)

标签: c# sql linq sql-server-2008 entity-framework


【解决方案1】:

Linq to Entities 中没有直接将字符串“解析”为 DateTimeTimeSpan 的方法,但您可以使用 SqlFunctionsDbFunctions 类来实现: p>

时间跨度

DbFunctions.CreateTime(SqlFunctions.DatePart("hh", timeString),
                       SqlFunctions.DatePart("mi", timeString), 
                       SqlFunctions.DatePart("ss", timeString));

日期时间

DbFunctions.CreateDateTime(SqlFunctions.DatePart("yy", dateString),
                           SqlFunctions.DatePart("mm", dateString),
                           SqlFunctions.DatePart("dd", dateString),
                           SqlFunctions.DatePart("hh", dateString),
                           SqlFunctions.DatePart("mi", dateString),
                           SqlFunctions.DatePart("ss", dateString));

【讨论】:

    【解决方案2】:

    在 EF 6.x 以下是不可能的。使用存储过程或在链接查询之前进行所有转换。

    【讨论】:

      【解决方案3】:

      您可以将数据加载到您的集合上的内存中(通过调用ToArray()ToList())并使用Convert.ToDateTime

      var date = DateTime.Today;
      var areEqual = dataContext.YourTable.ToList() 
              //now the data is in memory and you can apply whatever projection you want
              .Select(x => new{Date = Convert.ToDateTime(x.DateStringColumn)})
              .All(x => x.Date == date);
      

      但是,如果数据集非常大,这会增加内存使用量。为避免这种情况,请使用Where() 方法仅加载您需要的记录。

      【讨论】:

      • 这不是我想要的。如果数据库有数百万条记录呢? where 条件是基于那个时间比较的,所以我只会获取那些符合条件的记录,我无法将所有记录都提取到内存中并执行过滤。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-14
      • 2015-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多