使用Entity Framework Code First存储只读计算字段

11

我正在使用Entity Framework Code First,定义了一个实体,其中包含一个StartTime属性,一个EndTime属性和一个Duration属性(以及其他一些属性)。Duration属性是一个计算字段,它表示开始时间和结束时间之间的分钟数。以下是我的属性声明:

public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public int Duration
{
    get
    {
        return (int)this.EndTime.Subtract(this.StartTime).TotalMinutes;
    }
}

我想在代码中运行这个计算,但是希望将持续时间值与开始和结束时间值一起保存到数据库中(以便日后运行报告时更加方便)。我的问题是,如何通过Code First让这个只读属性映射回并保存到数据库中?

2个回答

21

在受到Slauma答案的启发下,我通过使用protected setter实现了自己的目标。这样可以将值持久化到数据库中,但是不允许在其他地方修改该值。

我的属性现在看起来像这样:

public int Duration
{
    get
    {
        return (int)this.EndTime.Subtract(this.StartTime).TotalMinutes;
    }
    protected set {}
}

啊,将其设置为受保护的是个好主意!你是否也尝试将 setter 设置为 private?如果 EF 仍然会将该属性映射到数据库列,那就很有趣了。 - Slauma
1
我刚刚尝试了使用private的setter,令人惊讶的是它仍然可以工作! - KevB
4
每当加载此实体时,EF都会更新数据库。我们猜测EF的更改跟踪错误地认为此属性已更改。这导致了意外的并发冲突。 - Brian Low
1
“错误地”?我不这么认为。如果您将实体加载到更改跟踪器中,然后调用保存更改,并且更改跟踪器执行其应该执行的操作并检查每个对象的“当前”值是否与数据库值匹配...它会发现刚刚计算出的当前值不同,并将保存该对象。这正是它应该工作的方式,而不是错误。 - Triynko

2
提供一个空的setter可能是一个可行的解决方案(当然,这样属性就不再是只读的了):
public int Duration
{
    get
    {
        return (int)this.EndTime.Subtract(this.StartTime).TotalMinutes;
    }
    set { }
}

据我所知,只读属性无法映射到数据库表的列中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接