C#/ EF核心:使用(历史)日期/期间

时间:2019-07-03 14:35:20

标签: c# asp.net-core-mvc entity-framework-core database-schema

使用SQL Server和EF Core使用ASP.NET Core Mvc创建C#网站。

对于一个爱好项目,我正在看旧报纸,文件并寻找特定的建筑物。每次找到此类建筑物的信息时,我都会尝试写下日期信息。这样我就可以跟踪这座建筑物在哪个时期。

因此,假设我遇到了Build X,并看到了日期1880。我记下了日期1880。 几周后,我再次遇到了X楼,看到日期:16/03/1877。我现在知道建筑物肯定在1877年3月16日到1880年间在那里。

时期:16/03/1877-1880

  • 现在有些建筑物没有日期信息。
  • 有些建筑物只有一个日期(也许可以通过额外的研究找到另一个日期)
  • 某些建筑物可能具有它在17世纪(没有特定的年份或日期)存在的信息。
  • 日期可以包含年,年+月或年+月+日

现在最好将其存储在数据库中并在模型中表示出来。

模型上的2个属性是否足够?

public class Building {
[DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
  public DateTime? Date1 { get; set; }
[DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime? Date2 { get; set; }
}

是否适合网站上的搜索过滤器。例如。搜索1830年至1930年之间的所有事物或17世纪的所有事物。

关于最后一个问题,我的意思是,如果仅给出一个建筑物的日期(例如1835),您将如何编写linq查询。如果只给出一个日期,每个查询都会包含一个可空日期的额外检查吗?还是有更好的方案?

.Where(x => x.Date1 != null && x.Date1 >= 1830 && (x.Date2 == null || x.Date2 <= 1930))

还是保存DateTime?对象不是一个好主意,最好存储短整数或整数,并且仅跟踪年份组成部分(如果有)?

1 个答案:

答案 0 :(得分:1)

确实,您的问题归结为显示确切日期与“模糊”日期。没有一个单一的策略,但是我之前有一个类似的要求,并通过一个开始日期,一个模糊的开始,一个结束日期和一个模糊的结束来处理它,所有这些都可以为空。

如果您完全知道日期的确切部分,请使用实际的datetime字段。例如,如果您只知道1880,则将其存储为1880-01-01。如果您知道年和月,则只需输入01,当然,如果您知道完整的日期,则可以存储该日期。现在,理所当然,这可能会带来问题。您怎么知道它并不是从1880年1月1日开始建造的,而仅仅是从1880年开始建造的?好吧,这取决于您决定如何处理这些情况。您可以假设任何01与该日期部分的空值相同。无论出于何种原因,建筑物都不会在1月1日或实际上在每个月的1号开放,但是那里总会有例外。

如果确实需要更高的精度,则可能需要分开日期并将其按字面量存储为年,月和日-所有可为int的int列。然后,您可以将其拼凑在一起,但是您希望在需要时进行展示。

“模糊”日期列将是字符串,并且您将在其中存储更多诸如“维多利亚时代”之类的星云“日期”,即您可能没有真实的日期甚至年份,但您知道它是在某个时期内时间。您可以对“ 19世纪”之类的东西进行同样的操作,但是我个人更喜欢将其存储为1800-01-01,然后暗示当有该日期时,它应该显示为“ 19世纪”。 / p>

另一个选择是同时使用日期和模糊文本。例如,您可以将其存储为1800-01-01 “ 19世纪”,然后根据模糊文本的存在来确定它实际上不是1800年1月1日。不为空。这可以帮助解决前面描述的歧义问题,因为您可以在所有此类情况下都这样做。例如,如果您只知道“ 1880年7月”,则可以将其存储在模糊文本中,并将日期设置为1880-07-01。然后,基于模糊文本的存在,您可以选择将01部分解密为基本上为空,而不是按月实际值。如果没有设置模糊文本,则假定它是确切的日期。

至于在模型上表示它,我不会使用实际的DateTime属性或DisplayFormat。拥有可以处理逻辑并返回预先格式化的“日期”的实用程序方法会更好。然后,您只需执行类似@building.GetBuiltDisplay()的操作,然后返回所有您已经知道的信息(包括开始和结束,如果有的话)就已经格式化了。