如果没有 Linq 对象的数据上下文,如何保存它?

2024-01-06

我有一个 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.

看来我有几个选择:

  1. 在我需要以这种方式使用的每个 Linq 类和表(100+)上放置一个版本成员。
  2. 找到最初创建该对象的数据上下文并使用它来提交更改。
  3. 在每个类中实现 OnLoaded 并保存该对象的副本,我可以将其传递给 Attach() 作为基线对象。
  4. 让并发检查见鬼去吧!在附加之前加载数据库版本并将其用作基线对象(不是!!!)

选项(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 并在仍然需要时保留它。

还有其他想法吗?


使用 LINQ to SQL 进行更新很有趣。

如果数据上下文消失了(在大多数情况下,应该如此),那么您将需要获取新的数据上下文,并运行查询来检索要更新的对象。 LINQ to SQL 中的一条绝对规则是,您必须检索一个对象才能将其删除,并且您也应该检索一个对象来更新它,这一点几乎是铁定的。有一些解决方法,但它们很丑陋,而且通常有更多方法让你陷入麻烦。因此,只需再次获取记录并完成即可。

重新获取对象后,请使用已更改的现有对象的内容更新它。然后对新的数据上下文执行 SubmitChanges()。就是这样! LINQ to SQL 将通过将记录中的每个值与原始(重新获取的)记录进行比较来生成相当严格的乐观并发版本。如果在您拥有数据时任何值发生更改,LINQ to SQL 将引发并发异常。 (因此您无需更改所有表的版本控制或时间戳。)

如果您对生成的更新语句有任何疑问,则必须打开 SQL Profiler 并观察更新到数据库的情况。这实际上是一个好主意,直​​到您对生成的 SQL 有信心为止。

关于事务的最后一个注意事项 - 如果没有环境事务,数据上下文将为每个 SubmitChanges() 调用生成一个事务。如果您有多个项目需要更新并希望将它们作为一个事务运行,请确保对所有项目使用相同的数据上下文,并等待调用 SubmitChanges(),直到更新了所有对象内容。

如果这种处理事务的方法不可行,则查找 TransactionScope 对象。它将成为你的朋友。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果没有 Linq 对象的数据上下文,如何保存它? 的相关文章

  • ASP.NET Core Serilog 未将属性推送到其自定义列

    我有这个设置appsettings json对于我的 Serilog 安装 Serilog MinimumLevel Information Enrich LogUserName Override Microsoft Critical Wr
  • 如何在 Silverlight 中使用 LINQ 创建 ObservableCollection

    在非 Silverlight 世界中 使用 LINQ 创建 ObservableCollection 很容易 这是因为 ObservableCollection 类具有接受任何 IEnumerable 或 List 的构造函数 然而Silv
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • 使闭包捕获的变量变得易失性

    闭包捕获的变量如何与不同线程交互 在下面的示例代码中 我想将totalEvents 声明为易失性的 但C 不允许这样做 是的 我知道这是错误的代码 这只是一个例子 private void WaitFor10Events volatile
  • 实时服务器上的 woff 字体 MIME 类型错误

    我有一个 asp net MVC 4 网站 我在其中使用 woff 字体 在 VS IIS 上运行时一切正常 然而 当我将 pate 上传到 1and1 托管 实时服务器 时 我得到以下信息 网络错误 404 未找到 http www co
  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • C#:如何防止主窗体过早显示

    在我的 main 方法中 我像往常一样启动主窗体 Application EnableVisualStyles Application SetCompatibleTextRenderingDefault false Application
  • 如果使用 SingleOrDefault() 并在数字列表中搜索不在列表中的数字,如何返回 null?

    使用查询正数列表时SingleOrDefault 当在列表中找不到数字时 如何返回 null 或像 1 这样的自定义值 而不是类型的默认值 在本例中为 0 你可以使用 var first theIntegers Cast
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • 指针减法混乱

    当我们从另一个指针中减去一个指针时 差值不等于它们相距多少字节 而是等于它们相距多少个整数 如果指向整数 为什么这样 这个想法是你指向内存块 06 07 08 09 10 11 mem 18 24 17 53 7 14 data 如果你有i
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • 控制到达非 void 函数末尾 -wreturn-type

    这是查找四个数字中的最大值的代码 include
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • Validation.ErrorTemplate 的 Wpf 动态资源查找

    在我的 App xaml 中 我定义了一个资源Validation ErrorTemplate 这取决于动态BorderBrush资源 我打算定义独特的BorderBrush在我拥有的每个窗口以及窗口内的不同块内
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐