【问题标题】:How to automatically generate identity for an Oracle database through Entity framework?如何通过实体框架为 Oracle 数据库自动生成身份?
【发布时间】:2011-03-08 03:23:45
【问题描述】:

我正在为实体框架(测试版)使用 Oracle 提供程序,但遇到了问题。

我们的表有 Id 列,在 StoreGeneratedPattern 中设置为 Identity。我认为 EF 会自动执行“基础工作”,例如创建序列,并为我添加到表中的每条记录获取新标识。但是当我运行代码添加一条新记录时,如:

var comment = new Comment
{
    ComplaintId = _currentComplaintId,
    Content = CommentContent.Text,
    CreatedBy = CurrentUser.UserID,
    CreatedDate = DateTime.Now
};

context.Comments.AddObject(comment);
context.SaveChanges();

一个异常仍然抛出,这是

{"ORA-00001: 唯一约束 (ADMINMGR.CONSTRAINT_COMMENT) 违反”}

(CONSTRAINT_COMMENT 是约束要求评论标识 必须是唯一的。

我该如何解决这个问题?

非常感谢!

【问题讨论】:

标签: c# .net oracle entity-framework ora-00001


【解决方案1】:

StoreGeneratedPattern="Identity" 只是告诉 EF 该值将在插入时在 DB 端生成,并且不应在插入语句中提供值。

你还需要在Oracle中创建一个序列:

create sequence ComplaintIdSequence minvalue 1 maxvalue 9999999 start with 1 increment by 1;

还有一个用于插入表格的触发器使用它:

create or replace trigger CommplaintIdTrigger  
before insert on comment for each row 
begin 
  if :new.ComplaintId is null then select ComplaintIdSequence.nextval into :new.ComplaintId from dual; 
  endif; 
end;

【讨论】:

  • 感谢您的回答,但我仍然无法相信 Oracle 没有自动执行此操作 :(
  • Oracle 绝对应该自动执行这些操作。 (因为它可以做的事情比你想象的更灵活。)理解(并隐藏)数据库平台之间的差异是你的框架的工作。
  • 我没有说 Oracle 应该在其数据库中执行此操作,但它绝对应该在其提供程序中执行此操作(您评论中的“框架”)
  • 在 Model-First 场景中我同意:如果表具有 int(或其他数字)主键storegeneratedpattern=identity...
  • 我同意 EF 应该对此进行抽象,但另一方面遗憾的是 sgdb 不能简单地增加一个值。甚至 MS Access 也能做到这一点。你可以在这里推荐:data.uservoice.com/forums/…
【解决方案2】:

Oracle 12c 已经解决了

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int SomeNumber { get; set; }

【讨论】:

    【解决方案3】:

    另一种选择是:

    按照 Alextansc 描述的方式创建一个序列。 创建一个使用 MySequence.nextval 作为主键的存储过程。

    将此模型的“插入”映射到您的存储过程,它就可以工作了!

    我已经使用数据库优先方法对此进行了测试。

    使用数据库优先映射到存储过程非常简单。转到您的 edmx 文件并右键单击要映射到存储过程的模型。单击“存储过程映射”。页面底部的对话框为您提供了三个下拉菜单,用于将插入、更新和删除映射到存储过程。

    【讨论】:

      【解决方案4】:

      我正在使用 Oracle ODP.NET、托管驱动程序和实体框架 6。我使用代码优先方法创建了我的表,但由于主键为空而无法添加任何记录。

      解决方案是同时授予我的用户:
      '创建序列'
      '创建触发器'
      权限并重新创建架构。

      我在包管理控制台中使用 -verbose 标志后意识到这一点

      【讨论】:

        【解决方案5】:

        您可以像这样使用Mig#,而不是记住所有这些 SQL:

                var schema = new DbSchema(ConnectionString, DbPlatform.Oracle12c);
                schema.Alter(db => db.CreateTable("TableName")
                    .WithPrimaryKeyColumn("Id", DbType.Int32).AsIdentity()
                    ...);
        

        在此示例中,Id 列将具有 Mig# 自动生成的所需触发器和序列。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多