如何在.NET实体框架中获取Oracle下一个序列值



我有一个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();

我遇到了同样的问题,并在该网站和Oracle的帮助下解决了它。我假设您使用的是数据库优先,因为您提到另一个遗留应用程序使用相同的数据库。

我不得不做一些事情。就像Daniel Gabriel提到的,如果你允许Oracle管理身份,你就不需要调用序列来找出号码,数据库会帮你处理它。但是要实现这一点有点棘手,因为您可能需要对数据库进行一系列更改。

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

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

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

    StoreGeneratedPattern="Identity"

VS实体框架中的Oracle实体不更新代码中的主键

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

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

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

然后在将该值添加到上下文之前,将其分配给新对象。

我的两分钱贡献:

string querySeq = "SELECT SCH.YOUR_SEQUENCE.NEXTVAL FROM DUAL";
var conn = (OracleConnection)dbContext.Database.GetDbConnection();
conn.Open();
var command = new OracleCommand(querySeq, conn);
decimal sequence = (decimal) command.ExecuteScalar();

您可以从上下文中获取数据库连接,并将其与OracleCommand类一起使用,以便直接使用ODP.net库执行SQL查询。

我用它作为参考:

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

Data/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;
   }

相关内容

  • 没有找到相关文章

最新更新