使用 EF Core 处理 MySQL 零日期
Posted
技术标签:
【中文标题】使用 EF Core 处理 MySQL 零日期【英文标题】:Handling MySQL Zero Date with EF Core 【发布时间】:2018-02-08 03:07:56 【问题描述】:背景:
我有 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'");
如果插入时没有发送任何值,这将正确存储零日期。
问题:
因为 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【问题讨论】:
问题:当您想要零日期时,为什么该字段是必需的(并且可以为空?)? 抱歉造成混淆,我将可空日期时间与我的支持现场测试结合使用。现已编辑。 但问题仍然存在:该字段是必需的,但您使用默认的空日期作为默认值。重点是;您是否使用此空日期来确保所有新条目默认过期?或者只是将字段标记为“未填充”的默认值。如果是后者,您可以允许NULL
(即不需要)并进行相同类型的检查以检查该字段的有效性。
使用 null 将字段标记为“未填充”是默认值,这不是一个选项,因为旧系统专门寻找零日期和/或隐式将其设置为零。
嗯,从某种意义上说,这更容易,因为您的选项集非常清晰;你真的需要在本地“修复”这个问题。只是在这里刷新我的想法,但是您可以调查几个“黑客”:1)在您的EF实体中使用[NotMapped]
属性,该属性将由原始sql语句填充。或 2) EF 提供一些自定义函数 EF/SQL 翻译,尽管我似乎找不到正确的术语。 ...或...
【参考方案1】:
人们可能会争辩说这更适合作为评论,但基本上,它太渴望了。
还有:
由于我手头没有可用的系统,因此您必须帮我一些忙,所以我是从头顶开始做的。 (我有点着急)
首先,从一个未映射的属性开始:
[NotMapped]
public DateTime ExpiryDate get; set;
此属性未映射。这可能会导致一些关于数据库与模型不匹配的错误,但我们可以克服它。查询数据时不会自动填充该属性。所以,我们需要一种方法来处理我们自己。
例如,(这是一个不好的例子,因为我们需要实体中某处的上下文):
[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
这里的基本问题;您想在 EF 框架内支持这一点多远?您是否只需要使用 EF 等的更改跟踪器读取或写入?
还有其他可能性,例如,在 SQL 本身中对 nvarchar 执行 CAST 以获取数据并进一步处理它。
也许ModelBuilder
提供了一些额外的选项。
【讨论】:
感谢您的所有建议。因为我需要使用 EF 和更改跟踪器来检索和存储这些日期,所以我得出的结论是,在插入/更新/添加时使用数据库触发器将 C# MinDate 转换为 MySQL 零日期会更干净。似乎 EF Core 将来会允许自定义类型映射,这应该可以解决这个问题:github.com/aspnet/EntityFrameworkCore/issues/242以上是关于使用 EF Core 处理 MySQL 零日期的主要内容,如果未能解决你的问题,请参考以下文章
使用 Devart.MySql 将 EF6 升级到 EF Core 3
EF CORE 2.1 HasConversion 在日期时间类型的所有属性上
从零开始搭建前后端分离的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的项目框架之七使用JWT生成Token(个人见解)