【问题标题】:DataContext disposed before updating foreign key field更新外键字段前配置的DataContext
【发布时间】:2011-01-26 19:55:46
【问题描述】:

我在将 linq to sql 用于 asp.net c# Web 应用程序的 DataContexts 中遇到了一些问题。

我首先遇到了抛出异常的问题,因为我没有处理 DataContext,与 this question 中的错误相同。我使用的是静态 DataContext,这可能是它没有被正确处理的原因,在阅读了 this 和其他几篇文章后,我将所有调用都包含在 using 语句中,以确保它们会被处理掉。

但是,现在当我需要更新外键时遇到了问题,因为 DataContext 已经被处理掉了。我不确定为什么它已经被处理掉了,以及在这种情况下最好的做法是什么,所以任何想法都将不胜感激!

这里是一个简短的例子:

更新:我认为我的示例在尝试使其尽可能短时过于混乱,因此这里有一个更长且希望更好的示例:

private static void SendTexts(List<TextAlert> TextQueue)
{
    using (THTDataContext db = new THTDataContext())
    {
        foreach (TextAlert text in TextQueue)
        {
            try
            {
                // do IntelliSMS stuff
                
                // set status to 'sent'
                text.Status = 1;

                db.SubmitChanges();
            }
            catch (IntelliSMSException ex)
            {
                // set status to 'failed'
                text.Status = 2;
                
                db.SubmitChanges();
            }
        }
    }
}

谢谢,

安妮莉

【问题讨论】:

  • 我一直想知道数字二的真正含义是什么,谢谢! ;) 说真的,神奇的数字已经出现了,enum 会更有效(就可读性而言,如果没有别的)。如果Status 属于enum 类型/值,那么我建议您使用正确的类型,而不是像这样分配值。题外话,我知道,但我认为这是不错的信息。
  • @Mr.失望 - 哈哈,我知道,应该从一开始就这样做,而不是采取快速的选择,它已经在我要做的事情清单上很久了。 :)
  • 很难从您的代码 sn-p 中猜出您实际在做什么:“MyThing”是由 Linq2SQL 创建的数据库记录,而 Status 是外键字段吗?
  • @Christoph - 对不起,我认为如果我保持简短会更容易,但我认为我做了相反的事情! :) 现在更新了我的问题。 MyThing 是我从数据库中获得的要发送的文本消息列表,是的,状态是外键字段。
  • 最好的解决方案(也与性能有关)可能是您可以保持原始 DataContext 活动直到您完成所有操作。如有必要,当您知道已完成时,显式 Dispose() 不使用 using 范围。

标签: c# .net linq-to-sql foreign-keys datacontext


【解决方案1】:

您可能需要将传入的MyThing 附加到您的新上下文中。这样的事情可能会奏效:

private static void DoMyStuff(MyThing thing)
{
    using (MyDataContext db = new MyDataContext())
    {
       db.MyThings.Attach(thing);
       thing.Status = 1;
       db.SubmitChanges();
    }
}

一旦它被附加,上下文应该能够跟踪它的变化,并在提交时存储它们。

如果这不能解决“已处理”异常,那么您可以在处理旧上下文之前尝试"detaching" MyThing。但是请注意,如果您必须走这条路,那么您的 DataContext 的生命周期可能是错误的,因为实体并非旨在在同一应用程序域中的上下文之间移动。

如果您有兴趣更好地了解附加/分离业务,MSDN 的 Dinesh Kulkarni 有一个关于它的 short blog post

【讨论】:

  • 收到错误消息“已尝试附加或添加一个不是新的实体,可能是从另一个 DataContext 加载的。不支持。”,但我会继续阅读当我更好地理解它时,您发送并返回链接。谢谢!
  • @annelie:那么可能是生命周期问题。这些链接应该会有所帮助,但结果是您可能需要扩大初始上下文的范围,以便您可以在该范围内DoMyStuff。典型的模式包括将 DataContext 存储在 HTTP 上下文(如果是 Web 应用程序)或线程本地存储(如果不是 Web 应用程序)中。祝你好运!
  • 刚刚做到了,现在它可以享受了!将 using 包裹在调用中以获取文本队列并发送它们并传递参考,不知道为什么我一开始没有这样做,但我要责怪我每天工作了三个 13 小时和我的大脑在这个截止日期之前无法修复任何错误。 ;) 非常感谢!
【解决方案2】:

哎呀!如果在尝试更新数据库中的条目时引发异常,您真的认为在异常处理程序中尝试更新数据库中的条目是个好主意吗?

至于这里发生了什么,thing的来源是什么?它是否来自在另一个MyDataContext 实例上执行的查询?如果是这样,那就是你的问题。

【讨论】:

  • 我使示例尽可能短,它实际上是我正在捕获的 IntelliSMSException(我正在尝试发送短信),数据库异常在其他地方处理。这样做仍然是一个坏主意吗?是的,事情的源头确实是在另一个实例上执行的。
  • +1 用于指出提交-捕获-提交。 @annelie,如果我是你并且我的目标是特定的异常类型,我会为那个确切的类型 (IntelliSMSException) 编写 catch 和/或仅将 try 块包装在抛出它的代码周围。完成后,您应该单独处理任何数据库错误。
  • @annelie:那就是问题所在。您需要将myThing 从前一个实例中分离出来,并将其附加到新实例。
  • @Justin Morgan - 我现在已经更新了我的问题,我正在捕捉那个确切的类型,只写了异常,因为我在这里写了一个尽可能短的例子(因为那不是问题的一部分,我认为这无关紧要)。
猜你喜欢
  • 2011-11-16
  • 1970-01-01
  • 2013-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-16
  • 2013-09-13
  • 2018-11-07
相关资源
最近更新 更多