【问题标题】:How to get Oracle next sequence value in .NET Entity Framework?如何在 .NET Entity Framework 中获取 Oracle 下一个序列值?
【发布时间】:2022-05-13 09:01:27
【问题描述】:

我有一个 web api post 方法,可以在我的 Oracle 数据库的表中插入一个新行。我在使用作为序列值的表的主键时遇到问题。如何在实体框架中执行my_primary_key_seq.nextval?目前此代码有效,但当通过我们使用序列下一个值作为下一个主键的旧 .net 网络表单插入新行时,它将违反 PK 唯一约束。

decimal nextPK = context.FORMPPs.OrderByDescending(p => p.PPID).FirstOrDefault().PPID + 1;
item.PPID = nextPK;
context.FORMPPs.Add(item);
int result = context.SaveChanges();

【问题讨论】:

  • 这并没有真正回答您的问题,但您也可以在实体的 ID 属性上放置一个属性(例如:[DatabaseGenerated(DatabaseGeneratedOption.Identity)]),这将导致自动生成主键。然后,您可以通过调用SaveChanges() 后获取实体的 ID 属性值来获取分配给新行的 ID。
  • 我可以通过将 1 添加到当前最大主键来插入新行,但它也不会增加 SEQUENCE 值,因此即使当前代码有效,如果有人使用旧的 .NET webform 网站,它会因为 SEQUENCE 编号不同步而中断。

标签: .net entity-framework oracle11g sequence nextval


【解决方案1】:

我遇到了同样的问题,并在本网站和 Oracle 的帮助下解决了这个问题。我假设您使用的是 Database First,因为您提到另一个旧应用程序使用相同的数据库。

我必须做几件事。就像 Daniel Gabriel 提到的那样,如果您允许 Oracle 管理身份,您无需调用序列来查找号码,数据库会为您处理。但是让它工作有点棘手,因为您可能需要对数据库进行大量更改。

  1. 在标识列上创建序列(您已经这样做了)。

  2. 创建一个触发器以在插入时自动调用序列。 http://www.oracle-base.com/articles/misc/autonumber-and-identity.php

  3. 更改您的实体框架模型。我使用的是 EF Database First,发现这篇文章解释了我需要更改模型以将表的标识列的属性设置为

    StoreGeneratedPattern="Identity"

Oracle entity in VS entity framework doesnt update the primary key in code

  1. 但我不喜欢每次从数据库刷新我的 EF 模型时都必须重新添加此更改的事实。双击 .edmx 文件,然后在数据库图中找到您的表,突出显示图中的标识列,然后在属性窗口中,将 StoreGeneratedPattern 值更改为 Identity。即使您更新 EF 模型,它也应该会持续存在。

【讨论】:

    【解决方案2】:

    我解决这个问题的方法是使用原始 SQL 查询从序列中选择一个新值。

    decimal nextPK = context.Database.SqlQuery<decimal>("SELECT my_primary_key_seq.nextval FROM dual").First();
    

    然后只需将此值分配给新对象,然后再将其添加到上下文中。

    【讨论】:

      【解决方案3】:

      我以此为参考:

      https://github.com/dotnet/EntityFramework.Docs/tree/main/samples/core/Querying/RawSQL

      数据/OracleSequenceContext.cs

      using Microsoft.EntityFrameworkCore;
      
       
      namespace EFQuerying.RawSQL;
      
      public class OracleSequenceContext : DbContext
      {
          public DbSet<OracleSequence> dbsetOracleSequences { get; set; }
      
          protected override void OnModelCreating(ModelBuilder modelBuilder)
          {
              modelBuilder
              .Entity<OracleSequence>(
                  eb =>
                  {
                      eb.HasNoKey();                
                  });
          }
      
          protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
          {
              // don't put this in code.
              optionsBuilder.UseOracle("Data Source=XXXXXXX;User ID=TTTTT;Password=PPPPP;");
          }
      }
      

      OracleSequence.cs

      using System.Collections.Generic;
      
      namespace EFQuerying.RawSQL;
       
      public class OracleSequence
      {
          public int SequenceValue { get; set; }
          
      
      }
      

      用法:

          using (var seqContext = new OracleSequenceContext())
          {
              var seqList = seqContext.dbsetOracleSequences
                  .FromSqlRaw("SELECT SEQ_PUBLICATION.NEXTVAL as SequenceValue FROM DUAL")
                  .ToList();
      
              Publication.PublicationId = seqList[0].SequenceValue;
         }
      

      【讨论】:

      • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-04
      • 2011-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多