【发布时间】:2022-01-01 20:58:14
【问题描述】:
我在我的项目中使用 ASP.NET Boilerplate MVC(非核心)模板,它使用 EF6 作为 ORM。数据库是 SQL Server Express。
这是我的实体对象(忽略不相关的属性):
public class Asset : AggregateRoot<long>
{
[DataType(DataType.DateTime)]
public DateTime? LastControlTime { get; set; }
}
当我创建一个新资产时,这个字段被适当地创建为 NULL。因此,一切都按照最初的意图进行。但是当我尝试通过简单的服务调用来更新对象时,它就搞砸了。
这是应用服务类中的方法:
public void ResetLastControlTime (EntityDto<long> input)
{
var asset = Repository.Get(input.Id);
asset.LastControlTime = default(DateTime?);
}
这应该将该字段重置为空。我也试过asset.LastControlTime = null;。但最后它在数据库中的该字段中写入了“0001-01-01 00:00:00.0000000”。我在代码中有很多地方可以控制为空值,所以现在我必须更改大量旧文件,否则我必须找到某种方法将该字段重置为简单的 NULL。
我在这里检查了类似的问题,但找不到答案。所有这些都讲述了我已经拥有的可为空的 DateTime。在 SQL server 表模式中,数据类型是datetime2(7),所以我想这也是正确的。哦,删除 DataType 注释也没有改变任何东西。
那么我在这里错过了什么?我应该检查什么才能发现问题?
【问题讨论】:
-
日期被转换为它的最小值,可能是因为在这种情况下,日期时间不能为空。也许在这种情况下,请尝试检查
DateTime.MinValue? -
你所有的代码和域模型看起来都是 Nullable,我还没有尝试过,但我猜 default(DateTime?) 在内存中时为 null。我只能想象你没有让实体框架创建你的数据库模式,如果是这样的话,那么也许 SQL 字段设置为 NOT NULL?如果 SQL 模式不能接受 Null,肯定会删除它们。如果您确实让 EF 来创建架构。如果您稍后添加 Nullable,您可能需要 Add-Migration & Update-Database
-
你有没有试过逐行调试和单步调试代码并观察
LastControlTime的值?如果您可以在单步执行代码时在每个点确定 this 的值,那么您应该能够隔离行为不符合预期的确切位置。从我所见,您发布的代码中没有任何内容会导致这种行为,但是您发布的代码中没有任何内容实际上涉及将资产保存到数据库,因此问题可能出在流程的其他地方. -
@MarkRabjohn 我的数据库是使用 Code First 方法创建的,所以它应该是 EF 创建的。虽然我添加了这一行,但我不记得在
OnModelCreating方法中添加了这一行:modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));我不知道这是否与问题有关。顺便说一句,我知道该字段可以为空,因为正如我所说,当创建一个新的 Asset 对象时,日期时间值从 NULL 开始。 -
@GarethD 好吧,保存部分由 ABP 的工作单元结构 afaik 处理。在应用程序服务方法完成后,它会自动将 C# 对象中所做的更改应用于数据库。虽然我想我可以找到一种方法来查看它发送到服务器的确切 SQL 命令。我可能会在那里捕捉到一些东西(虽然我不确定如何改变它)。
标签: c# asp.net-mvc entity-framework entity-framework-6 sql-server-express