1、DataContext为只读,相当于把DataContext.ObjectTrackingEnabled=false。只读的DataContext只能进行数据的查询,其他的操作都会抛出异常。
2、当调用Attach时,DataContext正在执行SubmitChanges()操作。
3、DataContext对象已经被显式调用Dispose()销毁。
4、asModified为true,但TEntity类的属性映射信息(MetaType)中包含 UpdateCheck=WhenChanged或UpdateCheck=Always设置。这是因为Attach的对象在当前DataContext 中并没有原始值的记录,DataContext无法根据UpdateCheck的设置生成where字句以避免并发冲突。需要说明的是几乎不会用到 asModified=true的调用,尤其是在对查询显示-用户修改-提交保存这样的Web应用场景,本文稍后会讨论这样的场景如何操作。如果坚持要用 asModified=true的调用,那么可以在TEntity类增加RowVersion属性的定义,LINQ2SQL引入RowVersion就是为了提供除UpateCheck以外的另一个冲突检测的方法,由于RowVersion应该在每一次更新操作后都应该修改,所以一般对应 Timestamp类型。
5、尝试Attach一个已属于当前DataContext上下文的对象。
6、尝试Attach的对象包含未载入的Assocation属性,或是未载入的嵌套Association属性。
其中原因(6)属于本文的讨论内容,我们来看看Attach函数中的调用
1 ...
2 if (trackedObject == null)
3 {
4 trackedObject = this.context.Services.ChangeTracker.Track(entity, true);
5 }
6 ...
Attach函数中调用StandardChangeTracker.Track(TEntity entity, bool recursive)方法,请注意第二个参数表示递归,Attach调用Track(entity, true)会导致entity的所有嵌套Association属性都会被检查。代码就是在StandardChangeTracker.Track中抛出了异常:
1 ...
2 if (trackedObject.HasDeferredLoaders)
3 {
4 throw Error.CannotAttachAddNonNewEntities();
5 }
6 ....