C# 实体框架自动编号

C# 实体框架自动编号,c#,entity-framework,exception,auto-increment,C#,Entity Framework,Exception,Auto Increment,我想循环遍历一组对象,并将它们全部添加到一个表中。目标表有一个自动递增字段。如果我添加一个对象,就没有问题了。如果我添加两个主键都为零的对象,实体框架将失败。我可以手动指定主键,但尝试EF的全部目的是让生活更简单,而不是更复杂。下面是代码和收到的异常 foreach (Contact contact in contacts) { Instructor instructor = InstructorFromContact(contact);

我想循环遍历一组对象,并将它们全部添加到一个表中。目标表有一个自动递增字段。如果我添加一个对象,就没有问题了。如果我添加两个主键都为零的对象,实体框架将失败。我可以手动指定主键,但尝试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()的 中的DataMigration.Program.CopyInstructors() C:\Projects\DataMigration\Program.cs:第52行


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

之所以会出现这种情况,是因为尽管在数据库中创建了自动生成的列值,但EF从未知道它

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

您的实体类型定义大致如下所示:

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

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


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

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

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


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

我猜,如果您将“自动编号”字段留空,当您提交时,数据库将为您分配一个。是的,它可以工作,它会添加记录并分配主键。问题是,对于这种典型的场景,我不应该得到异常。我确信在框架中有一种“正确”的方法可以做到这一点,只是不确定如何做到。现在,在我对表进行了一些杂项更改并更新了模型之后,异常停止了抛出。不知道是什么造成了不同。我所做的唯一更改是为列添加一些默认值,并将这些列设置为NOTNULL。不确信这些更改与异常有关。听起来可能很傻,但在我们的例子中,触发器中有一个不必要的select语句,它使触发器返回数据和SaveChanges()实际上,我花了相当长的时间来执行并最终抛出了上述错误。我认为我的错误之处在于,我最初是从数据库创建模型的,但忘记了设置“自动编号”字段。LaterI编辑了我的数据库并设置了此属性,然后在visual studio 2010中使用“从数据库更新模型”命令。更新功能似乎添加了新属性,但不确定是否正确“修复”了现有的修改属性。通过删除我的模型并从头开始重新创建,自动编号功能按预期工作。然而,如果我知道的更好,我会尝试你的想法。目前(但希望很快!)我没有使用EF4,但我在本页中读到一些关于这一点的内容:Microsoft在这里为VS2010SP1提供了一个修补程序。它似乎对我有用。@kimsk链接不再有用了。我需要下载什么?听起来可能很傻,但在我们的例子中,触发器中有一个不必要的select语句,它使触发器返回数据,SaveChanges()实际上花了相当长的时间执行,最终抛出了上述错误。请注意,您不能只在设计器中设置此属性,您必须手动编辑SSDL部分。我读过了这个答案,然后想:“我已经做过了。”,我一直在寻找,我可以通过注意到SSDL来节省时间,这是设计师中的一个已知错误。您可能想参与进来:我们正在使用VS2012、EF 5和ODP.NET for Oracle 11启动一个新的MVC 4项目,我们遇到了完全相同的问题。每次“从模型生成数据库”时,edmx文件上的ssdl部分都会丢失“storedGeneratedPatter=Identity”属性。有人知道VS2012和EF 5也有支持Oracle的修补程序吗?听起来可能很傻,但在我们的例子中,触发器中有一个不必要的select语句,它使触发器返回数据,SaveChanges()实际上花了相当长的时间执行,最终抛出了上述错误。