我有一个 Linq 对象,我想对其进行更改并保存它,如下所示:
public void DoSomething(MyClass obj) {
obj.MyProperty = "Changed!";
MyDataContext dc = new MyDataContext();
dc.GetTable<MyClass>().Attach(dc, true); // throws exception
dc.SubmitChanges();
}
例外的是:
System.InvalidOperationException: An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.
看来我有几个选择:
- 在我需要以这种方式使用的每个 Linq 类和表(100+)上放置一个版本成员。
- 找到最初创建该对象的数据上下文并使用它来提交更改。
- 在每个类中实现 OnLoaded 并保存该对象的副本,我可以将其传递给 Attach() 作为基线对象。
- 让并发检查见鬼去吧!在附加之前加载数据库版本并将其用作基线对象(不是!!!)
选项(2)似乎是最优雅的方法,特别是如果我可以找到一种在创建对象时存储对数据上下文的引用的方法。但是——怎么办?
还有其他想法吗?
EDIT
我尝试遵循 Jason Punyon 的建议,在表上创建一个并发字段作为测试用例。我在 dbml 文件中的字段上设置了所有正确的属性(时间戳 = true 等),现在我有一个并发字段...和一个不同的错误:
System.NotSupportedException: An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported.
那么,如果不是现有的实体,我到底应该附加什么呢?如果我想要一条新记录,我会执行 InsertOnSubmit()!那么你应该如何使用 Attach() 呢?
编辑 - 全面披露
好吧,我知道是时候全面披露为什么所有标准模式都不适合我了。
我一直在努力通过向“消费者”开发人员隐藏 DataContext 来变得聪明并使我的界面更加清晰。我通过创建一个基类来完成此操作
public class LinqedTable<T> where T : LinqedTable<T> {
...
}
...我的每个表都有其生成版本的“另一半”声明,如下所示:
public partial class MyClass : LinqedTable<MyClass> {
}
Now LinqedTable
有很多实用方法,最特别的是:
public static T Get(long ID) {
// code to load the record with the given ID
// so you can write things like:
// MyClass obj = MyClass.Get(myID);
// instead of:
// MyClass obj = myDataContext.GetTable<MyClass>().Where(o => o.ID == myID).SingleOrDefault();
}
public static Table<T> GetTable() {
// so you can write queries like:
// var q = MyClass.GetTable();
// instead of:
// var q = myDataContext.GetTable<MyClass>();
}
当然,正如你可以想象的那样,这意味着LinqedTable
必须以某种方式能够访问 DataContext。直到最近我才实现这一点caching静态上下文中的 DataContext。是的,“直到最近”,因为“最近”是当我发现你不应该在 DataContext 上停留超过一个工作单元的时间,否则各种各样的小妖精就会开始出现。学过的知识。
所以现在我知道我不能在该数据上下文上保留太久...这就是为什么我开始尝试按需创建 DataContext,仅缓存在当前LinqedTable
实例。这导致了新创建的 DataContext 不想与我的对象有任何关系,因为它“知道”它对创建它的 DataContext 不忠实。
有没有办法在创建或加载时将 DataContext 信息推送到 LinqedTable 上?
这确实是一个装腔作势的人。我绝对不想在我放入的所有这些便利功能上妥协LinqedTable
基类,并且我需要能够在必要时释放 DataContext 并在仍然需要时保留它。
还有其他想法吗?