实体框架"无法为标识列插入显式值"

时间:2016-10-23 22:49:51

标签: .net database entity-framework ef-code-first asp.net-core

我正在使用带有EF的.NET Core,并且在尝试添加到数据库时遇到了问题。我有一个名为Map的复杂JSON对象,它包含其他实体类型。 SourceField出现错误,它可以在RuleSourceFields和Conditions中,它们本身就在Map中。我已经检查过以确保我的外键和主键是正确的,但是没有修复它。除非我弄错了,否则我认为添加一个拥有虚拟成员的实体不应该导致EF尝试添加该子实体?请注意,此错误仅发生在SaveChanges()。

错误:

{System.Data.SqlClient.SqlException: Cannot insert explicit value for identity column in table 'SourceFields' when IDENTITY_INSERT is set to OFF.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
   at System.Data.SqlClient.SqlDataReader.TryHasMoreResults(Boolean& moreResults)
   at System.Data.SqlClient.SqlDataReader.TryNextResult(Boolean& more)
   at System.Data.SqlClient.SqlDataReader.NextResult()
   at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.Consume(DbDataReader reader)
ClientConnectionId:3bc06159-276e-4a39-bbb9-7c66999e255f
Error Number:544,State:1,Class:16}

我发送的JSON示例:

{  
   "description":"test",
   "effective_Date":"2016-10-23T18:59:49.3855195",
   "active":true,
   "transformations":[  
      {  
         "description":"sdfsdf",
         "rule":{  
            "rule_Value":"",
            "alt_Value":"",
            "rule_Operation":"sfield",
            "targetField":{  
               "targetFieldId":1,
               "name":"TEST",
               "datatype":"text",
               "active":true,
               "seqNum":1,
               "rules":[  

               ],
               "targetId":1,
               "target":null,
               "created_By":"Anonymous",
               "creation_Date":"2016-10-23T18:59:49.3855195",
               "date_Modified":"2016-10-23T18:59:49.3855195",
               "modified_By":"Anonymous"
            },
            "ruleSourceFields":[  

            ]
         },
         "conditions":[  
            {  
               "seqNum":1,
               "chain_Operation":"or",
               "left_Paren":"(",
               "operation":"!=",
               "cond_Value":"sdf",
               "right_Paren":")",
               "sourceField":{  
                  "sourceFieldId":28,
                  "name":"N/A",
                  "datatype":"text",
                  "active":true,
                  "seqNum":2,
                  "conditions":[  

                  ],
                  "ruleSourceFields":[  

                  ],
                  "sourceId":19,
                  "source":null,
                  "created_By":"Anonymous",
                  "creation_Date":"2016-10-12T04:51:03.3311291",
                  "date_Modified":"2016-10-12T04:51:03.3311291",
                  "modified_By":"Anonymous"
               }
            }
         ]
      }
   ]
}

模型类示例:

SourceField.cs

        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int SourceFieldId { get; set; }
        public string Name { get; set; }
        public string Datatype { get; set; }
        public bool Active { get; set; }
        public int SeqNum { get; set; }

        [ForeignKey("SourceFieldId")]
        public virtual ICollection<Condition> Conditions { get; set; }
        [ForeignKey("SourceFieldId")]
        public virtual ICollection<RuleSourceField> RuleSourceFields { get; set; }

        public int SourceId { get; set; }
        public virtual Source Source { get; set; }

Condition.cs

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ConditionId { get; set; }
    public int SeqNum { get; set; }
    public string Chain_Operation { get; set; }
    public string Left_Paren { get; set; }
    public string Operation { get; set; }
    public string Cond_Value { get; set; }
    public string Right_Paren { get; set; }

    public int SourceFieldId { get; set; }
    public virtual SourceField SourceField { get; set; }

    public int TransformationId { get; set; }
    public virtual Transformation Transformation { get; set; }

1 个答案:

答案 0 :(得分:1)

我认为您的JSON中显示的sourceField sourceFieldId=28已经存在且您不想插入它,对吧?并且您的父实体没有附加到上下文,因为您只是从JSON填充它(您没有从数据库上下文中获取它)。

您的孩子SourceField实体的EF跟踪状态似乎未正确设置为UnchangedModified,而是Added。这是在断开连接的场景中处理实体图时遇到的问题。您可以使用GraphDiff来解决这个问题,this answer会通过您的子树,并确保正确设置每个孩子的状态。或者您可以自己实现并手动更新孩子的跟踪状态。

有关这种情况发生的原因以及如何在Release notes of Spring Boot 1.4.0中修复此问题的详细信息。

此外,如果您不打算更新sourceField子项的内容,如果您的JSON仅包含属性sourceFieldId的值而不是整个导航,则可能会避免此问题实体sourceField

使用虚拟导航属性的目的是允许EF在执行延迟加载时使用代理实体。据我所知,他们对允许添加或修改子实体没有任何影响。