使用 EF Core 处理 MySQL 零日期

Ban*_*ito 5 c# mysql entity-framework entity-framework-core

背景: 我有 200 多个遗留的 VB6 应用程序,我正在将它们转换为 C#,使用 EntityFramework Core 作为我们的 ORM。不幸的是,许多应用程序都使用 MySQL 的零日期(0000-00-00)。所以我需要满足这一点并能够以某种方式存储零日期。目前还无法改变 200 多个应用程序中的基本工作方式。

设置: 我可以定义一个代表 MySQL 中字段定义的实体属性,例如:

 public DateTime ExpiryDate { get; set; }

...

 entity.Property(e => e.ExpiryDate)
                       .IsRequired()
                       .HasColumnType("datetime")
                       .HasDefaultValueSql("'0000-00-00 00:00:00'");
Run Code Online (Sandbox Code Playgroud)

如果插入时没有发送值,这将正确存储零日期。

问题: 因为 C# 有一个最小日期,所以0001-01-01 我不可能显式存储零日期。所以我的问题是...有没有办法设置我的实体以将这个零日期放入和取出数据库?

到目前为止: 我已经尝试使用支持字段,定义为字符串,以便我可以操纵任何DateTime.MinValue成为'0000-00-00'. 这允许我存储零日期,但在尝试检索数据时会导致转换问题(如您所料):

System.InvalidCastException:无法将“System.DateTime”类型的对象转换为“System.String”类型。

我当前使用的软件包是:

  • EFCore 1.1
  • PomeloEntityFrameWorkCore 1.1.2
  • MySQL 5.7.18

Ste*_*fan 0

人们可能会说这更适合作为评论,但基本上,这是太渴望了。

和:

你必须帮我一些忙,因为我手头没有可用的系统,所以我是从头开始做这件事的。(而且我有点着急)

首先,从未映射的属性开始:

[NotMapped]
public DateTime ExpiryDate { get; set; }
Run Code Online (Sandbox Code Playgroud)

该属性未映射。这可能会导致一些有关数据库与模型不匹配的错误,但我们可以克服它。查询数据时不会自动填充该属性。因此,我们需要一种方法来解决这个问题。

例如,(这是一个不好的例子,因为我们需要实体中某处的上下文):

[NotMapped]
public DateTime? ExpiryDate 
{
    get
    {
         //of course you'll need some caching here
         var s = context.Database.SqlQuery<string>("query to select datetime as string");
         //additional logic to determine validity:
         if (s == "0000-00-00")
             return null;
         //else:
         //do the conversion
    }
 }
Run Code Online (Sandbox Code Playgroud)

这里的基本问题;您想在 EF 框架内支持这一点到什么程度?您只需要读取它,还是使用EF等更改跟踪器也可以写入?

还有其他可能性,例如,在 SQL 本身内对 nvarchar 执行CAST,以获取数据并进一步处理它。

也许ModelBuilder会暴露一些额外的选项。