我有一些这样的代码:
Activity[] GetAllActivities() {
using (ScheduleContext ctx = new ScheduleContext())
return ctx.Activities.AsNoTracking().ToArray();
}
目标是为某些数据提供一个非常简单的内存缓存:Activities
映射到db视图,该视图总结了我需要的所有内容。
如果我省略 AsNoTracking
,则返回的对象被非确定性地破坏:返回的对象的属性设置不正确,并且通常一个对象的属性值在其他对象中重复属性。没有警告或例外;既不是EF4.3.1也不是EF5rc2。 CLR 4和4.5候选版本都表现出相同的行为。
Activity
个对象非常简单;仅包含基本类型的非虚拟属性(int
,string
等),并且与任何其他实体没有密钥或关系。
这是预期的行为吗?我在哪里可以找到关于此的文档?
我理解,一旦相关DbContext
消失,显然更改跟踪无效,但我很惊讶物化属性在没有警告的情况下被破坏。我最担心的是,在一个更复杂的场景中,我会忘记AsNoTracking
,并且会得到一些看似合理但错误的结果。
编辑 该实体如下所示。谢谢Jonathan&克里斯托夫;确实有一个列被推断为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; }
...
答案 0 :(得分:3)
我认为“经常有一个对象的属性值在其他对象的属性中重复”,并且Activity
对象“并且没有键”是这里的关键信息(没有双关语意)。
导入View(显然没有主键)时,EF会猜测主键是什么。如果随后启用了跟踪,则它使用该主键确保在内存中仅创建每个实体的单个副本。这意味着如果您为字段加载两行具有相同值的EF,则猜测PK是PK,第二行的值将覆盖第一行。
对于“非确定性损坏”的数据,这可能是因为数据库不保证返回行的顺序,并且它是EF中的“最后胜利”过程,因此如果订单记录的变化来自DB,保持其值的记录也会发生变化。
尝试将更多列标记为主键的一部分,或者修改视图(或EDMX中的DefiningQuery)以包含基于ROW_NUMBER function的列,以便您可以将其用作主键。