实体框架服务器端计算值

时间:2016-06-05 15:28:34

标签: c# asp.net .net entity-framework entity-framework-6

我正在消耗一个具有以下课程时间的api。

public class CRTime
{
    public DateTime? datetime { get; set; }
    public string timezone { get; set; }
}

我想将其转换为单个DateTime字段。

以下是返回给我的完整对象的示例,以及我如何计算将存储在数据库中的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 AddOrUpdate。

2 个答案:

答案 0 :(得分:2)

这是因为AddOrUpdate的一个相当混乱的怪癖。

显然,

AddOrUpdate确定实体是新的还是现有的。它通过主键或您可以指定的某个键查询实体的数据库来实现。现在可能发生两件事:

  • 它在数据库中找不到实体;您的实体对象标记为Added
  • 确实找到了一个实体,但与您预期的实体对象相反仍然是Detached!找到的实体仍然是隐藏的,这是EF最终更新的对象。它会将您自己实体的值复制到它,这可能会将隐藏的实体标记为Modified

显然,通过这个空的setter,CreatedDB在从数据库中取出时始终为null。对于EF,CRCreated不存在。它可能会从您的对象中读取CreatedDB值,但空的setter会阻止它被复制到隐藏对象,并且会更新为null

你必须决定如何解决这个问题。可能最好的方法是让setter实际修改(或创建)CRCreated实例。

或者,您可以取消AddOrUpdate并尝试自己查找现有对象。如果你发现它,它就不会被隐藏了,所以你可以随心所欲地使用它。

答案 1 :(得分:1)

从Db读取后我希望它为NULL。 private set;当然很奇怪,阻碍了EF的正常运作。

当你能够使用DateTimeOffset但在目前的情况下,你可以帮助自己:

您的财产可能会按逻辑'计算'但是对于数据库,它应该被视为正常的读/写属性。