【问题标题】:Linq DataContext doesn't recover after a caught exception?Linq DataContext 在捕获异常后无法恢复?
【发布时间】:2009-01-22 20:06:30
【问题描述】:

我是第一次使用 LINQ,我遇到了一些我对 DataContext 不完全理解的行为。希望 StackOverflow 可以提供帮助。

基本上,似乎一旦我的 DataContext 遇到异常,它要么缓存该异常,要么永远不会完全恢复。在我的具体情况下,一旦我尝试将一个太大的字符串传递给我的数据库,它会为所有后续字符串抛出相同的异常。

我有一张这样的桌子:

 DisplayString(
  StringID nvarchar(255)
  ,CultureCode varchar(25)
  ,DisplayString nvarchar(255)
 )

在 .Net 中,我创建了一个 DataContext,我使用 LINQ to SQL 类将其映射到该表。

Dim context As New LinqTableMappingDataContext(
  My.Settings.LocalizationStringsConnectionString)

然后我创建一堆测试字符串,遍历每个字符串并将它们发送到我的表。

Dim arr As String() = 
  {"aaaaa",  "adsfs", "wefwf", "dfgsfg", "ergsdfg", 
   "fsdgergd", "Sdgdfgegd", "ergdfgsfd"}

  For Each a As String In arr
     addToLinq(a)
  Next

这很好用。但是,如果我在索引 1 处添加以下字符串,所有后续插入都会失败,抛出与长字符串相同的异常 (SqlException)。

"WARNING: This computer program is protected by copyright law and international
treaties. Unauthorized reproduction of this program, or any portion of it, may
result in severe civil and criminal penalties, and will be prosecuted to the
maximum extent possible under the law."

这是我的 AddToLinq() 方法。

Private Sub AddToLinq(ByVal stringID As String)

  Dim f As New DisplayString
  Try

     Dim count As Integer = (From str In context.DisplayStrings _
       Where str.StringID = stringID Select str).Count

     If count = 0 Then

        f.StringID = stringID
        f.CultureCode = "en-US"
        f.DisplayString = stringID

        context.DisplayStrings.InsertOnSubmit(f)
        context.SubmitChanges()
        Console.WriteLine("SUBMITTED: " & stringID)
    End If

  Catch ex1 As SqlException
     Console.WriteLine("------------------------------------------------")
     Console.WriteLine("EXCEPTION: " & ex1.Message)
     Console.WriteLine(stringID)
     Console.WriteLine(stringID.Length)
     Console.WriteLine("------------------------------------------------")

  Catch ex As DuplicateKeyException
     Console.WriteLine(ex.Message)

  End Try
End Sub

如果有人可以帮助我,那就太好了,谢谢。

【问题讨论】:

    标签: .net vb.net linq


    【解决方案1】:

    如果您观察 DataContext 的 GetChangeSet method,您会发现它仍想插入第一个字符串。这就是它无法恢复的原因。

    【讨论】:

      【解决方案2】:

      每次需要时都创建一个新上下文,而不是重用全局/静态上下文成员。问题是您的上下文对象处于错误状态。

      ....
      if (count = 0)
         Dim context As New [Your context here]
         ....
      end if
      

      【讨论】:

      • 我的上下文成员是一个实例变量。您需要为每个插入创建一个新的上下文成员,这似乎有点矫枉过正/荒谬?
      • @Charlie - 应该为每批相关更改创建一个新的上下文(基本上每次调用 SaveChanges 时)。例如,您可以插入多个 DisplayString 对象并一次更改现有对象(即调用 SaveChanges 时)。
      • @confusedGeed - 这是有道理的,最初我只保存了一次,但是在调试时我更改了结构以保存每次迭代。我可能会恢复到旧样式。
      【解决方案3】:

      它实际上在同一个插入上失败了,因为您没有从数据上下文中删除失败的字符串,并且每次调用 SubmitChanges 时它都会尝试插入它。正如@confusedGeek 建议的那样,您可以通过为每个插入实例化一个新的数据上下文来解决这个问题。或者,您可以将 ConflictMode 设置为 ContinueOnConflict,我相信其余的更改将被插入。由于您在每次添加时都提交更改,因此我会选择前一种解决方案并为每个插入创建单独的上下文。

      编辑:另一种选择是让您的异常处理程序处理旧上下文并在出错时创建一个新上下文。我不确定这是否是一个很大的改进——似乎比必要的要复杂一些。数据上下文是非常轻量级的实体,所以我不会太担心根据需要创建一个新实体。

      【讨论】:

      • 感谢 tvanfosson,我原本只想在遍历所有字符串后才保存,因此我可以设置 ConflictMode。我没有意识到数据上下文有你说的那么轻量级。
      猜你喜欢
      • 1970-01-01
      • 2021-09-02
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      • 2010-10-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多