使用实体框架自动编号

时间:2010-06-10 05:05:40

标签: c# entity-framework exception auto-increment

我想遍历一组对象并将它们全部添加到表中。目标表具有自动增量字段。如果我添加一个对象没有问题。如果我添加两个主键为零的对象,则实体框架失败。我可以手动指定主键,但尝试EF的重点是让生活变得更轻松而不是更复杂。这是代码,接收的异常如下。

foreach (Contact contact in contacts)
{               
    Instructor instructor = InstructorFromContact(contact);             
    context.AddToInstructors(instructor);               
}

try
{                   
    context.SaveChanges();                  
}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
}

错误是:

  

System.InvalidOperationException :已成功提交对数据库的更改,但更新时发生错误   对象上下文。 ObjectContext可能处于不一致状态。   内部异常消息:AcceptChanges无法继续因为   对象的键值与其中的另一个对象冲突   ObjectStateManager。确保密钥值之前是唯一的   调用AcceptChanges。在   System.Data.Objects.ObjectContext.SaveChanges(SaveOptions选项)
  在System.Data.Objects.ObjectContext.SaveChanges()at   DataMigration.Program.CopyInstructors()in   C:\ Projects \ DataMigration \ Program.cs:第52行

4 个答案:

答案 0 :(得分:18)

在自动增量字段的SSDL中将StoreGeneratedPattern属性设置为“Identity”。它应该有所帮助。

答案 1 :(得分:12)

这是因为尽管在数据库中创建了列的自动生成值,但EF从未知道它。

因此,为了通知EF数据库将处理生成的值,您必须打开edmx文件(我总是使用VS的XML编辑器来执行此操作)和商店架构定义语言(SSDL)区域,将属性 StoreGeneratedPattern =“Identity”添加到需要生成的模式的列中。通过这种方式,EF读取DB中生成的值并将其存储在内存缓存中。

您的实体类型定义或多或少会像这样:

 <EntityType Name="INVOICE">
          <Key>
            <PropertyRef Name="CODE" />
          </Key>
          <Property Name="CODE" Type="varchar" Nullable="false"
              MaxLength="10" StoreGeneratedPattern="Identity"/>                 
 </EntityType>

请注意,如果您碰巧更新了模型,所有这些更改都将丢失,您将不得不重复所有整个过程。

这适用于EF 1.0,我不确定在EF4中是否所有这些问题都已修复。

答案 2 :(得分:3)

我使用EF6设置StoreGeneratedPattern,您也可以尝试在Visual Studio中打开EDMX文件,右键单击表格中的数据列并选择属性,

然后,您可以在属性窗口中将其从None设置为Identity

答案 3 :(得分:0)

可能听起来很傻,但在我们的例子中,触发器中有一个不必要的 select 语句,它使触发器返回数据,而 SaveChanges() 实际上花费了相当长的时间来执行并最终抛出上述错误。