4

我有一些这样的代码:

Activity[] GetAllActivities() {
  using (ScheduleContext ctx = new ScheduleContext())
    return ctx.Activities.AsNoTracking().ToArray();
}

目标是对一些数据进行非常简单的内存缓存:Activities映射到一个数据库视图,该视图总结了我需要的所有内容。

如果我省略 AsNoTracking返回的对象是不确定的损坏:返回对象的属性设置不正确,并且经常一个对象的属性值在其他对象的属性中重复。没有警告或异常;既不在 EF4.3.1 也不在 EF5rc2 上。CLR 4 和 4.5 候选版本都表现出相同的行为。

Activity对象非常简单;int仅由基本类型( 、等)的非虚拟属性组成string,没有键,也没有与任何其他实体的关系。

这是预期的行为吗?我在哪里可以找到有关此的文档?

我知道一旦相关DbContext信息消失,显然更改跟踪就无法工作,但我很惊讶物化属性在没有警告的情况下被破坏。我主要担心我会AsNoTracking在更复杂的场景中忘记某个地方,并得到一些看似合理但错误的结果。

编辑:实体如下所示。谢谢乔纳森和克里斯托夫;确实有一列被推断为ID!

public class Activity
{
  public string ActivityHostKey { get; set; }
  public int ActivityDuration { get; set; }
  public int ActivityLastedChanged { get; set; }
  public string ActivityId { get; set; }//!!!
  public string ModuleHostKey { get; set; }
  public string ModuleName { get; set; }
...
4

1 回答 1

3

我认为“经常一个对象的属性值在其他对象的属性中重复”并且Activity对象“并且没有键”是这里的关键信息(不是双关语)。

导入视图(显然没有主键)时,EF 会猜测主键是什么。如果随后启用了跟踪,它会使用该主键来确保在内存中只创建每个实体的一个副本。这意味着如果您为 EF 猜测为 PK 的字段加载具有相同值的两行,则第二行的值将覆盖第一行。

至于“非确定性损坏”的数据,这可能是因为数据库不保证返回行的顺序,并且它是 EF 中的“最后获胜”过程,所以如果记录的顺序从数据库中更改,保留其值的记录也会更改。

尝试将更多列标记为主键的一部分,或修改视图(或 EDMX 中的 DefiningQuery)以包含基于ROW_NUMBER 函数的列,以便您可以将其用作主键。

于 2012-07-07T13:02:33.663 回答