C# 如何使用实体框架在Oracle中使用序列插入标识值

C# 如何使用实体框架在Oracle中使用序列插入标识值,c#,oracle,entity-framework,oracle-manageddataaccess,C#,Oracle,Entity Framework,Oracle Manageddataaccess,在Oracle数据库中,其ID列定义为数字: …以及表的相应序列…: 如何确保ID列获得序列中的下一个值 using (var db = new MyOracleDb()){ var user= new User(){ first_name = 'Abe', last_name = 'Lincoln'}; //Do something here with the sequence and set the ID? db.User.Add(user); db.Sa

在Oracle数据库中,其ID列定义为数字:

…以及表的相应序列…:

如何确保ID列获得序列中的下一个值

using (var db = new MyOracleDb()){
    var user= new User(){ first_name = 'Abe', last_name = 'Lincoln'};
    //Do something here with the sequence and set the ID?
    db.User.Add(user);
    db.SaveChanges();
}

我使用的是最新的Oracle.ManagedDataAccess和Oracle.ManagedDataAccess.EntityFramework+EF6x。

这不是EF问题,因为Oracle中没有自动增量。 您必须手动获取序列值, 或者创建一个为您设置的

更新 为了获得序列值,您有两个选项—创建一个返回值的存储过程—或创建一个.Net函数( 不一定要在函数中,只是更简单而已) 这就叫原始SQL 像这样:

Database.SqlQuery(“从dual中选择SEQ_SOMESEQ.NEXTVAL”)


我个人在oracle函数和EF方面有很多问题,所以我会使用原始sql。

仅供参考,在实体框架方面,我有一些独特的约束问题。如果您仍然存在独特的约束问题,请提供给未来的读者。请确保将属性“StoreGeneratedPattern”更改为您的要求

对我来说,我添加了MAX(ID)+1,并将StoreGeneratedPattern设置为Identity,它开始正常工作,但在某个时候通过抛出相同的唯一约束问题打破了整个程序,当我检查数据库时,情况绝对不是这样。这是大多数开发者没有注意到的事情


我把它改为“无”,所以我可以控制它添加什么,而不是每隔几天实体框架就会破坏它

如果您在Oracle端创建触发器,您不必在代码中担心它。它的工作原理就像它有一个标识一样。

我创建了一个接口:

public interface IHasSequencer
{
    decimal Id { get; set; }
    string GetSequenser();
}
然后在我的模型中实现它:

[Table("CLN_CLIENTS")]
public class ClnClient : IHasSequencer
{
    public string GetSequenser()
    {
        return "SEQ_CLN_CLIENTS";
    }

    [Key, Column("ID")]
    public decimal Id { get; set; }

    [Column("FIRSTNAME")]
    public string FirstName { get; set; }

    [Column("LASTNAME")]
    public string LastName { get; set; }

    [Column("MIDDLENAME")]
    public string MiidleName { get; set; }
}
并在my DbContext中添加了一些神奇的覆盖SaveChanges()方法:

 public override int SaveChanges()
    {
        var addedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Added);

        foreach (DbEntityEntry entry in addedEntries)
        {
            if (entry.Entity is IHasSequencer)
            {
                var sequencerEntity = entry.Entity as IHasSequencer;
                var nextSeqVal = Database.SqlQuery<Int64>("SELECT " + sequencerEntity.GetSequenser() + ".NEXTVAL FROM DUAL").First();
                sequencerEntity.Id = nextSeqVal;
            }
        }
        return base.SaveChanges();
    }
public override int SaveChanges()
{
var addedEntries=ChangeTracker.Entries(),其中(e=>e.State==EntityState.Added);
foreach(附录中的DbEntityEntry)
{
if(entry.Entity为IHasSequencer)
{
var SequenceRenty=entry.Entity作为IHasSequencer;
var nextSeqVal=Database.SqlQuery(“选择“+sequencerenty.getsequencer()+”.NEXTVAL FROM DUAL”).First();
SequenceRenty.Id=nextSeqVal;
}
}
返回base.SaveChanges();
}

就这样!现在,需要Sequencer ID值的模型必须实现小型接口。

我也这么认为,但如何使用EF检索序列中的下一个值?在这种情况下,修改表(或添加触发器)不是一个选项。很好,我现在得到了值。:)真棒的解决方案!我对界面做了一点修改,使其能够更新PK不称为“Id”的表。我在接口上添加了一个名为“SetIdFromSequencer”的方法,并在更新PK的实体上重写了该方法。在保存更改时,我将
sequencerenty.Id=…
更改为
sequencerenty.SetIdFromSequencer(nextSeqVal)