【问题标题】:Comparing OffSetDateTime's Date part with Today in EF/Linq with NodaTime将 EF/Linq 中 OffSetDateTime 的日期部分与今天与 NodaTime 进行比较
【发布时间】:2021-09-24 11:48:42
【问题描述】:

我正在使用 ASP.NET 核心 3.1。 我正在尝试检索今天已完成的会话列表。

我可以像这样检索所有已完成的会话:

var zonedClock = SystemClock.Instance.InTzdbSystemDefaultZone();
OffsetDateTime now = zonedClock.GetCurrentOffsetDateTime();

return _context.Session
.Where(x => (Local.Compare(x.EndDateTime, now) <0))
.Include(o => o.Tournaments)
.ToList<Session>();

其中 EndDateTime 是 NodaTime OffsetDateTime,Local 是 OffsetDateTime.Comparer。但是,当我尝试也像这样匹配日期时:

return _context.Session
.Where(x => (Local.Compare(x.EndDateTime, now) <0)
 && x.StartDateTime.Date.Equals(now.Date))
.Include(o => o.Tournaments)
.ToList<Session>();

我收到以下错误:

InvalidOperationException: The LINQ expression 'DbSet<Session>()
.LeftJoin(
inner: DbSet<Venue>(),
outerKeySelector: s => EF.Property<Nullable<int>>(s, "VenueId"),
innerKeySelector: v => EF.Property<Nullable<int>>(v, "VenueId"),
resultSelector: (o, i) => new TransparentIdentifier<Session, Venue>(
Outer = o,
Inner = i
))
.Where(s => __Local_0.Compare(
x: s.Outer.EndDateTime,
y: __now_1) >= 0 && s.Outer.StartDateTime.Date.Equals(__now_Date_2) && s.Inner == __Venue_3 && s.Outer.Lane == __Lane_4)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.<VisitMethodCall>g__CheckTranslated|15_0(ShapedQueryExpression translated, ref <>c__DisplayClass15_0 )

添加 .AsEnumerable() 似乎没有帮助。

有什么想法吗?

【问题讨论】:

  • 您在哪里尝试添加 AsEnumerable()?我绝对希望这有助于更改在进程中而不是在数据库中执行的比较。
  • (尽管使用Include(o =&gt; o.Tournaments) 可能是这里的问题。)
  • 您可能想找到一种方法,首先在数据库中进行“可能过于宽泛”的过滤,然后对内存中的结果进行更精确的过滤。
  • 如果我把它放在 Include 之前,它会拒绝编译,所以它就在 .ToList 之前
  • 我认为Local.Compare 不能翻译成SQL。

标签: entity-framework linq asp.net-core nodatime


【解决方案1】:

我解决了这个问题。需要在开始时包含锦标赛表,然后在 .Where 之前使用 .AsEnumerable 然后从静态生成比较器的实例,如下所示:

return  _context.Session
            .Include(o => o.Tournaments)
            .AsEnumerable()
            .Where(x => (OffsetDateTime.Comparer.Local.Compare(x.EndDateTime, now) <0)
             && x.StartDateTime.Date.Equals(now.Date))
            .ToList<Session>();

【讨论】:

  • 这是一种解决方法。包含详细信息的整个表被加载到内存中。
  • 是的,它是次优的
猜你喜欢
  • 1970-01-01
  • 2012-05-10
  • 2013-04-06
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多