我正在使用一个具有以下时间类的 api。
public class CRTime
{
public DateTime? datetime { get; set; }
public string timezone { get; set; }
}
我想将其转换为单个日期时间字段。
下面是返回给我的完整对象的示例,以及我如何尝试计算随后将存储在数据库中的 DateTime 字段。
public class ReturnObject
{
[NotMapped]
// This comes from the api, but is not synced to database
public CRTime CRCreated { get; set; }
// this is stored in our db, should be calculated from CRCreated
public DateTime? CreatedDB { get
{
var val = (CRCreated != null) ? CRCreated.datetime : null;
return val;
}
private set { }
}
// other fields go here
}
这在记录创建时非常有效,但是当我尝试使用 Entity.Migration 框架和 AddOrUpdate 更新记录时,更新会覆盖该值并始终将其设置为 NULL。
创建服务器端计算列然后同步到数据库的最佳解决方案是什么。
旁注:我使用 NewtonSoft Json 将对象反序列化到我的 Entity Framework 对象中,然后将其传递给 Entity Framework AddOrUpdate。
最佳答案
这是因为 AddOrUpdate
的一个相当令人困惑的怪癖。
AddOrUpdate
确定实体是新的还是现有的。它通过按实体的主键或您可以指定的某个键在数据库中查询实体来实现这一点。现在可能会发生两件事:
- 在数据库中找不到该实体;您的实体对象被标记为
已添加
。 - 它确实找到了一个实体,但与您的预期相反,您的实体对象仍然
分离
!找到的实体仍然隐藏,这就是 EF 最终更新的对象。它将值从您自己的实体复制到其中,这可能会将隐藏实体标记为已修改
。
显然,通过这个空 setter ,从数据库获取CreatedDB
时,它始终为null
。对于 EF,CRCreated
不存在。它可能从您的对象中读取一个 CreatedDB
值,但空的 setter 再次阻止它被复制到隐藏对象,并且它被更新为 null
。
您必须决定如何解决这个问题。也许最好的方法是让 setter 实际修改(或创建)CRCreated
实例。
或者,您可以取消 AddOrUpdate
并尝试自己查找现有对象。如果你找到了它,它就不再隐藏了,所以你可以用它做任何你喜欢的事情。
关于c# - Entity Framework 服务器端计算值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37643563/