【问题标题】:For Each Loop LINQ Insert giving me Cannot add an entity that already exists对于每个循环 LINQ 插入给我无法添加已存在的实体
【发布时间】:2012-06-04 04:05:41
【问题描述】:

我有以下代码,在我的脑海中应该在表格中创建一个新行:

Dim fin As Boolean
Dim db2 As New ChecklistModeldbmlDataContext
For Each a In bServers

   If collection("fin" & a.ServerName) = "true, false" Or collection("fin" & a.ServerName) = "true,false" Then
       fin = True
   Else
       fin = False
   End If

   bLog.AMLogID = amLog.LogID
   bLog.ByteCount = collection("bytes" & a.ServerName)
   bLog.DurationHours = collection("hours" & a.ServerName)
   bLog.DurationMinutes = collection("minutes" & a.ServerName)
   bLog.DurationSeconds = collection("seconds" & a.ServerName)
   bLog.IsFinished = fin
   bLog.ServerID = a.ServerID
   bLog.DetailsAndErrors = collection("details" & a.ServerName)

   db2.BackupLogs.InsertOnSubmit(bLog)
   db2.SubmitChanges()
Next

它只会在表中添加一条记录,然后出现无法添加已存在的实体的错误。

现在它应该在表中输入 4 行,但我不知道为什么上面给了我这个错误。

我也尝试将 db2.SubmitChanges() 放在 for each 之外,它只是插入最后一行。

有什么想法吗?

【问题讨论】:

    标签: asp.net-mvc vb.net linq-to-sql foreach


    【解决方案1】:

    您没有在循环中创建新的博客。在每次迭代中,您只是修改单个记录的数据。

    尝试使用 new 关键字创建一个新的 bLog 实例,然后在 ForEach 循环中为其分配数据

    【讨论】:

    • bLog 在哪里声明呢?它应该在循环内声明。
    • 我只是在它之外声明。现在它在里面,问题解决了。
    【解决方案2】:

    关于代码的另一件事:

    If collection("fin" & a.ServerName) = "true, false" Or collection("fin" & a.ServerName) = "true,false" Then
       fin = True
    Else
       fin = False
    End If
    

    这段代码有几个问题。

    1. 首先,不要编写设置布尔变量的If 条件。条件已经所需的值。而是直接写:

      fin = collection("fin" & a.ServerName) = "true, false" Or _
            collection("fin" & a.ServerName) = "true,false"
      

      这是真的一般来说。所以每当你有这样的代码时:

      If condition Then
          value = True
      Else
          value = False
      End If
      

      将其重写为value = condition始终。没有例外。或者如果值被反转,则分配否定结果,即value = Not condition

    2. 其次,从不在布尔条件中使用 AndOr。这些是位操作,它们在布尔条件下是没有意义的。当然,它们产生了正确的结果,但这只是巧合。

      正确的解决方案是使用AndAlsoOrElse加入条件。在你的情况下,这将是:

      fin = collection("fin" & a.ServerName) = "true, false" OrElse _
            collection("fin" & a.ServerName) = "true,false"
      

      这不仅更合乎逻辑,而且效率更高,因为条件的第二部分仅在必要时才被评估,即当条件的第一部分尚未评估为 True 时(与 @ 正好相反987654333@).

    3. 最后,你为什么只在循环内部使用fin?始终尝试将声明放在最接近其首次使用的位置。因此,这意味着您应该始终立即初始化一个值。

      所以从循环之前删除fin 的声明并更正里面的赋值:

      Dim fin As Boolean = collection("fin" & a.ServerName) = "true, false" OrElse _
                           collection("fin" & a.ServerName) = "true,false"
      

      如果您已正确设置 Visual Studio,以便 VB 项目选项 Option ExplicitOption StrictOption Infer 都是 On(您应该这样做!)您可以甚至在上面的声明中省略As Boolean,因为从上下文中很明显fin 必须是Boolean,并且编译器正确地推断出这一点。

    【讨论】:

    • 为什么这到底是被否决了?!如果答案有问题,请编辑或发表评论,以便我更正。如果您不同意这个特定的答案,请获得生命。答案提出了最佳实践,完全没有争议。
    【解决方案3】:

    您绝对应该在For Each 循环中新建bLog

    【讨论】:

      【解决方案4】:

      博客的实例来自哪里?看起来它是在循环之外创建的。因此,在每次通过时,您都在修改 blog 的实例,而不是添加一个新实例。一旦第一个被保存,它就有一个 id,你不能再调用 InsertOnSubmit 了。您应该为每次迭代中的任何 bLog 创建一个新实例。

      一旦你解决了这个问题,你应该只在循环外调用SubmitChanges

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-01
        • 1970-01-01
        • 2011-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-05
        • 2020-06-17
        相关资源
        最近更新 更多