【问题标题】:InsertOnSubmit = Cannot add an entity with a key that is already in useInsertOnSubmit = 无法使用已在使用的键添加实体
【发布时间】:2009-05-13 02:05:19
【问题描述】:

我正在尝试使用 Linq 将记录插入到表中,但遇到了可怕的 Cannot add an entity with a key that has been in use 错误

'If the same data exists for the same patient in a record less that 21 days old then drop it
Dim RecordLookup As Integer = 0
RecordLookup = (From rc In CDEvodb.RISKCHANGEs _
    Where rc.NHI = tmpNHI And _
    rc.RECDATE > Date.Now.AddDays(-21) And _
    rc.BPSYS = Convert.ToDecimal(Drow.Item("BPSYS")) And _
    rc.CHOL = Convert.ToDecimal(Drow.Item("CHOL")) And _
    rc.HDL = Convert.ToDecimal(Drow.Item("HDL"))).Count()
If (RecordLookup = 0) Then
Dim riskchange As New RISKCHANGE
    riskchange.NHI = Drow.Item("NHI")
    riskchange.RECDATE = Date.Now.Date()
    riskchange.RISK = CalculatedRisk
    riskchange.BPSYS = Drow.Item("BPSYS")
    riskchange.CHOL = Drow.Item("CHOL")
    riskchange.HDL = Drow.Item("HDL")

    Try
        CDEvodb.RISKCHANGEs.InsertOnSubmit(riskchange)
    Catch ex As Exception
        myLogging.OutputError("<" & DateTime.Now.ToString & "> " & "Error - creating risk change record in dataset for patient " & Drow.Item("NHI").ToString() & " - " & ex.Message)
    End Try

End If

基本上,我在表中查找不到 21 天的匹配记录(不包括身份字段)。如果找不到,我会创建一个行的实例并设置为插入它。

SubmitChanges 函数被调用了几行。

Drow 是来自先前使用 SQLClient 连接填充的 Dataset 的 DataRow(原因是我还没有完全转换到 Linq,现在只是在做新功能)。

提前干杯。


这是表的创建脚本:

USE [CDEvolution]

/****** 对象:表 [dbo].[RISKCHANGES] 脚本日期:05/13/2009 14:40:15 ******/

设置 ANSI_NULLS 为开

设置 QUOTED_IDENTIFIER 开启

设置 ANSI_PADDING 为开

创建表 [dbo].[RISKCHANGES](

[NHI] [varchar](7) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,

[RECDATE] [datetime] NOT NULL,

[RISK] [numeric](15, 0) NOT NULL,

[BPSYS] [numeric](15, 0) NOT NULL,

[CHOL] [numeric](15, 1) NOT NULL,

[HDL] [numeric](15, 1) NOT NULL,

[POSTED] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,

[IDENTITY] [uniqueidentifier] NOT NULL CONSTRAINT [DF_RISKCHANGES_IDENTITY]  

默认 (newid()),

CONSTRAINT [PK_RISKCHANGES] 主键集群

(

[IDENTITY] ASC

)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]

) 开启 [主要]

设置 ANSI_PADDING 关闭

【问题讨论】:

  • 你能发布表格架构吗?

标签: vb.net linq-to-sql


【解决方案1】:

如果您更新 DBML,请将 (IsDbGenerated="true") 添加到 PK 成员:

    <Column Name="[IDENTITY]" Member="IDENTITY" Type="System.Guid" 
            DbType="UniqueIdentifier NOT NULL" IsPrimaryKey="true" 
            CanBeNull="false" IsDbGenerated="true"/>

它将让 SQL 分配默认值 (newid())。

否则它将发送未初始化的 guid ('00000000-0000-0000-0000-000000000000'),据我所知,这基本上是导致问题的原因。

您的其他选择可能是扩展部分类并在 OnCreated() 事件中初始化 GUID(不使用列的 newid() 默认值,但确实解决了问题:

    partial class RISKCHANGE
    {
        partial void OnCreated()
        {
            _IDENTITY = Guid.NewGuid();
        }
    }

请注意,对于现有实体(由查询填充),在处理 OnLoaded() 时,此值将被正确的值覆盖。

【讨论】:

  • 传奇!工作了一个款待。感谢那些做出贡献的人:-)
【解决方案2】:

你的主键是什么?你还有其他的键/约束吗?它可能是导致问题的原因之一。我建议扩大匹配记录的搜索范围,或更改您的约束条件。

【讨论】:

    【解决方案3】:

    嘿,凯文,快速提问,可能很愚蠢,但只是为了获得更好的想法......

    您在新的 riskchange 对象上设置的任何属性是主键属性吗?

    另外,在调用 SubmitChanges() 之前你还做了什么?

    干杯

    编辑:

    感谢凯文。这条线是怎么回事?:

    [IDENTITY] [uniqueidentifier] NOT NULL CONSTRAINT [DF_RISKCHANGES_IDENTITY]
    

    你对PK有什么限制...?为什么看起来不像:

    [IDENTITY] [int] IDENTITY(1,1) NOT NULL
    

    ?

    编辑 嘿凯文。我认为问题在于您没有将 PK 设置为身份说明符,因此它不会自动增加 P​​K。

    要解决此问题,请通过更改此行重新创建表:

    [IDENTITY] [uniqueidentifier] NOT NULL CONSTRAINT [DF_RISKCHANGES_IDENTITY]
    

    到这里:

    [IDENTITY] [int] IDENTITY(1,1) NOT NULL
    

    或者,如果您使用 Mangement Studio,只需进入该表的设计。转到该字段的属性,然后在属性窗口(通常出现在下面)中将“身份规范”(Is Identity)设置为“是”。

    别忘了更新您的 LINQ 2 SQL DBML

    【讨论】:

    • 嗨,我没有在新的 RISKCHANGE 对象上设置任何属性。在 SubmitChange() 之前,我更新了另一个数据集中的 RISK 值。上面的代码也在循环中。我的想法是我扫描另一个 DataSet 中的所有行,看看我是否可以在 Linq DataContext 表中找到少于 21 天的匹配行。如果可以,那么我插入该行。希望这会有所帮助
    • 哦,一旦循环完成,就会调用 SubmitChange()
    • 只是再次阅读您的问题:正如您在下面的脚本中看到的那样,我必须创建一个主键,因此使用了一个身份字段。我在查询和写入表时没有引用它,据我所知这是自动生成的,设置为 GUIDRow。
    • 第一次尝试 Linq 时,它需要表上的主键来进行插入,所以我添加了 IDENTITY 字段,将其设置为唯一标识符并将其设置为主键而不是 null .上面的脚本是我在 SQL Server Management Studio 中创建表时生成的。我接受我可能做了一些愚蠢的事情,所以如果有更好的方法来做我想做的事情并且帮助将不胜感激。干杯。
    • 如果我将该字段设置为一个简单的非空 int,那么我需要生成一个唯一值以插入该字段。如果我将它作为 GUIDRow 获取,那么会为它自动生成一个。或者至少我是这么理解的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-18
    • 2021-07-03
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多