0

我想显示从现在到下一天过生日的员工的信息。

这是我的疑问。_dayrm 的函数是参数

Dim query = (From emp In Context.UNI_EMPLOYEE_CV.ToList
                         Select New RemindDTO With {
                             .EMPLOYEE_CODE = emp.UNI_EMPLOYEE.EMPLOYEE_CODE,
                             .FULLNAME = emp.UNI_EMPLOYEE.FULLNAME,
                             .REMIND_DATE = emp.BIRTHDATE}).ToList.Distinct

Dim result = (From emp In query
                             Where emp.REMIND_DATE IsNot Nothing AndAlso
                             ((DateTime.Now >= New Date(DateTime.Now.Year, emp.REMIND_DATE.Value.Month, emp.REMIND_DATE.Value.Day).AddDays(-_dayrm)) And
                             (DateTime.Now <= New Date(DateTime.Now.Year, emp.REMIND_DATE.Value.Month, emp.REMIND_DATE.Value.Day)))
                             Select emp)

Return result.ToList()

我使用了 entityframework 和 oracle 数据库

但它在“选择 p”中出现错误,并显示消息“年、月和日参数描述了无法表示的日期时间”。

4

2 回答 2

0

Oracle 日期时间格式不同。使用 to_date 函数以所需的格式传递它,然后使用它在您的查询中进行操作。

于 2013-10-19T09:02:25.360 回答
0

首先,您需要考虑数据库将如何处理此操作。在您当前的代码中,因为您ToList在第一行的末尾调用,所以对您的数据库进行的唯一查询是这样的:

SELECT * FROM UNI_EMPLOYEE_CV

接下来的一切都ToList在内存中完成。换句话说,您正在检索整个表。

那么你应该在你的数据库上执行什么查询呢?嗯,这有点棘手。为了获得良好的性能,所有查询都应该能够使用索引。否则,他们必须扫描整个表。通常,任何时候您编写的查询必须在比较之前修改数据库中的字段,这就是一个必须扫描表的每一行的查询。在某些情况下,它可能会扫描索引的每一行,但这也不好。您需要的是搜索,而不是扫描

所以退后一步,想想你在做什么。您想查询生日在特定范围内的所有员工。但是由于今年是他们的生日,所以您没有可以在其上创建索引的列。每一行都必须将其数据调整为当前年份。

这将在此处详细讨论。我认为最好的解决方案是MatBailie的解决方案。基本上,您需要创建一个附加列并使用年份固定为 2000 的数据填充它。然后您需要为该列建立索引。(我不是 Oracle 专家,但我相信如果您无法更改表架构,您也可以使用物化视图上的索引来执行此操作。在 SQL Server 中,您可以使用索引视图。)

因此,让我们假设您已经完成了此操作,并且现在BIRTHDAY_Y2K您的数据库中有一个名为的列。现在你可以这样做:

Dim today As DateTime = DateTime.Today
Dim startDate As DateTime = new DateTime(2000, today.Month, today.Year)
Dim endDate As DateTime = startDate.AddDays(_dayrm)

If endDate.Year = 2000 Then

    Dim query = (From emp In Context.UNI_EMPLOYEE_CV
                 Where emp.BIRTHDAY_Y2K >= startDate
                   And emp.BIRTHDAY_Y2K <= endDate
                )
Else

    endDate = endDate.AddYears(-1)

    Dim query = (From emp In Context.UNI_EMPLOYEE_CV
                 Where emp.BIRTHDAY_Y2K >= startDate
                    Or emp.BIRTHDAY_Y2K <= endDate
                )
End If

拆分的原因是为了涵盖诸如在 12 月 20 日运行 30 天并且仍然像 1 月 10 日这样的生日这样的场景。

我认为您可以从此处完成每个查询。ToList()在从您的方法返回数据之前,您应该只在每个结束时调用一次。

另外,只是为了回答您之前评论中的一些问题:

  • 您对 2 月 29 日的日期有疑问,因为它只存在于闰年。如果年份不是闰年,则将 2 月 29 日分配给任意年份将失败。由于我们在上面的代码中使用了 2000 年,所以 2 月 29 日的生日是安全的。

  • 您不想在一个操作中调用DateTime.NowDateTime.Today多次调用,因为每次调用它时它都必须从系统时钟中读取。由于时钟总是在滴答作响,如果一个电话和下一个电话之间的日子发生变化,您可能会遇到问题。一般来说,这是一种不好的做法,并且还会导致某些操作出现性能问题。

于 2013-10-20T17:14:26.160 回答