如何在.NET Entity Framework中获取Oracle的下一个序列值?

8

我有一个web api的post方法,它会在我的Oracle数据库表中插入一行新数据。我在处理表的主键时遇到了问题,这个主键是一个序列值。在Entity Framework中如何实现my_primary_key_seq.nextval呢?目前这段代码是有效的,但当我们在旧的.NET WebForm中使用序列下一个值作为下一个主键插入新行时,将违反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。 - Daniel Gabriel
我可以通过将当前最大主键加1来插入新行,但这并不会增加SEQUENCE值,因此即使当前代码有效,如果有人使用旧的.NET Webform网站插入新行,它也会出现问题,因为SEQUENCE号码不同步。 - iCanObjSeeSharp
4个回答

5
我解决这个问题的方法是使用原始SQL查询从序列中选择一个新值。
即。
decimal nextPK = context.Database.SqlQuery<decimal>("SELECT my_primary_key_seq.nextval FROM dual").First();

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


5
我曾经遇到过同样的问题,通过这个网站和Oracle的帮助解决了它。我假设您正在使用Database First,因为您提到另一个旧应用程序使用相同的数据库。
有几件��情我必须要做。像Daniel Gabriel提到的那样,如果您允许Oracle管理身份标识,您就不需要调用序列以查找号码,数据库会为您处理。但要使其正常工作可能有些棘手,因为您可能需要对数据库进行一些更改。
1.在身份标识列上创建序列(您已经完成了这一步)。 2.创建触发器以自动调用插入序列。(参考http://www.oracle-base.com/articles/misc/autonumber-and-identity.php) 3.修改Entity Framework模型。我使用的是EF Database First,并发现这篇文章说明我需要修改模型来设置表的身份标识列的属性,如下所示:StoreGeneratedPattern="Identity" 4.我不喜欢每次从数据库刷新EF模型时都要重新添加此更改的事实。双击.edmx文件,然后在数据库图中找到您的表,在图中突出显示身份标识列,在属性窗口中将StoreGeneratedPattern值更改为Identity。这样即使更新EF模型,它也会持续存在。
参���链接:Oracle entity in VS entity framework doesnt update the primary key in code

1

我的贡献:

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查询。


0

我把这个作为参考:

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

目前你的回答不够清晰。请编辑并添加更多细节,以帮助其他人理解它如何回答所提出的问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接