使用实体框架自动编号

Posted

技术标签:

【中文标题】使用实体框架自动编号【英文标题】:Autonumber with Entity Framework 【发布时间】:2011-03-02 00:06:44 【问题描述】:

我想遍历一组对象并将它们全部添加到表中。目标表有一个自动增量字段。如果我添加一个对象没有问题。如果我添加两个主键为零的对象,实体框架就会失败。我可以手动指定主键,但尝试 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 无法继续,因为 对象的键值与另一个对象冲突 对象状态管理器。确保之前的键值是唯一的 调用 AcceptChanges。在 System.Data.Objects.ObjectContext.SaveChanges(SaveOptions 选项) 在 System.Data.Objects.ObjectContext.SaveChanges() 在 DataMigration.Program.CopyInstructors() 在 C:\Projects\DataMigration\Program.cs:第 52 行

【问题讨论】:

我猜如果你把自动编号字段留空,当你提交时数据库会为你分配一个。 是的,它可以工作,它会添加记录并分配主键问题是我不应该在这种典型情况下遇到异常。我确信在框架内有一种“正确”的方法,只是不确定如何。 好吧,在我对表格进行了一些杂项更改并更新了模型后,现在异常停止抛出。不知道是什么造成了不同。我所做的唯一更改是为列添加一些默认值并将这些列设置为不为空。不相信这些更改与异常有关。 可能听起来很傻,但在我们的例子中,触发器中有一个不必要的 select 语句使触发器返回数据,并且 SaveChanges() 实际上需要相当长的时间来执行并最终引发上述错误。 【参考方案1】:

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

【讨论】:

【参考方案2】:

我用的是EF6,要设置StoreGeneratedPattern,你也可以尝试在Visual Studio中打开EDMX文件,右击表中的Data Column并选择Properties,

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

【讨论】:

【参考方案3】:

发生这种情况是因为尽管在数据库中创建了列的自动生成值,但 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 中是否所有这些问题都已修复。

【讨论】:

我认为我出错的地方在于我最初从数据库创建模型并忘记设置自动编号字段。后来我编辑了我的数据库并设置了这个属性,然后是 Visual Studio 2010 中的“从数据库更新模型”命令。更新功能似乎添加了新属性,但不确定它是否正确“修复”了现有的修改属性。通过删除我的模型并从头开始重新创建,自动编号功能按预期工作。不过,如果我知道得更多,我会尝试你的想法。 目前(但希望很快!)我没有使用 EF4,但是我在这个页面上读到了一些关于这个的内容:geeksharp.com/2010/05/27/ef4-bug-in-storegeneratedpattern-ssdl 微软在此处为 VS2010SP1 提供了一个修补程序。 connect.microsoft.com/VisualStudio/Downloads/…这似乎对我有用。 @kimsk 该链接不再有效。我需要下载什么? 可能听起来很傻,但在我们的例子中,触发器中有一个不必要的 select 语句使触发器返回数据,并且 SaveChanges() 实际上需要相当长的时间来执行并最终引发上述错误。 【参考方案4】:

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

【讨论】:

请注意,您不能只在设计器中设置此属性,您必须手动编辑 SSDL 部分。我读过这个答案并想:“我已经这样做了。”,我一直在寻找,我可以通过注意到 SSDL 来节省几个小时这是设计器中的一个已知错误。 geeksharp.com/2010/05/27/ef4-bug-in-storegeneratedpattern-ssdl 和 social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/… 你可能想要权衡一下:meta.stackexchange.com/questions/82509/… 我们正在使用 VS2012、EF 5 和 ODP.NET for Oracle 11 开始一个新的 MVC 4 项目,我们遇到了完全相同的问题。每次我们“从模型生成数据库”时,edmx 文件上的 ssdl 部分都会丢失“storedGeneratedPatter=Identity”属性。有人知道支持 Oracle 的 VS2012 和 EF 5 的任何修补程序吗? 可能听起来很傻,但在我们的例子中,触发器中有一个不必要的 select 语句使触发器返回数据,并且 SaveChanges() 实际上需要相当长的时间来执行并最终引发上述错误。

以上是关于使用实体框架自动编号的主要内容,如果未能解决你的问题,请参考以下文章

使用带有代码优先的实体框架,没有自动增量

在模型中使用多对多时访问实体框架自动生成的第三个表

Symfony,如何显示对象的正常名称而不是实体编号

尽管代理被禁用,实体框架会自动设置关系

JFinal极速开发框架使用笔记 _JFinalDemoGenerator实体类生成及映射自动化

使用T4模板为EF框架添加实体根据数据库自动生成字段注释的功能