【问题标题】:How to insert identity value in Oracle using Entity Framework using a sequence如何使用实体框架使用序列在 Oracle 中插入标识值
【发布时间】:2017-03-15 22:37:18
【问题描述】:

在 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。

【问题讨论】:

    标签: c# oracle entity-framework oracle-manageddataaccess


    【解决方案1】:

    这不是 EF 问题,因为 oracle 中没有自动增量。 您将不得不手动获取序列值, 或创建一个trigger 为您设置。

    更新

    为了获得序列值,您有两个选择 - 创建一个返回值的存储过程 - 或创建一个 .Net 函数( 不一定要在函数中,它只是更简单) 调用原始 SQL 像这样:

    Database.SqlQuery<int>("SELECT SEQ_SOMESEQ.NEXTVAL FROM dual");

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

    【讨论】:

    • 我想了很多,但是如何使用 EF 检索序列中的下一个值?在这种情况下,修改表(或添加触发器)不是一种选择。
    • 太棒了,我现在把价值拿出来了。 :)
    【解决方案2】:

    仅供参考,使用实体框架时,我遇到了独特约束的问题。对于未来的读者,如果您仍然遇到独特的约束问题。请确保将属性“StoreGeneratedPattern”更改为您的要求。

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

    我已将其更改为“无”,因此我可以控制要添加的内容,而不是每隔几天就破坏它的实体框架。 Entity Framework Property Picture

    【讨论】:

      【解决方案3】:

      如果您在 Oracle 方面创建触发器,则不必担心代码中的问题。它就像有一个身份一样工作。

      【讨论】:

        【解决方案4】:

        我已经创建了一个界面:

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

        并在我的 DbContext 中添加了一些 MAGIC 覆盖 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();
            }
        

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

        【讨论】:

        • 很棒的解决方案!我对界面进行了一些更改,以便可以更新 PK 不称为“Id”的表。我在名为“SetIdFromSequencer”的接口上添加了一个方法,并在更新 PK 的实体上覆盖了此方法。在 SaveChanges 上,我将 sequencerEntity.Id = ... 更改为 sequencerEntity.SetIdFromSequencer(nextSeqVal);
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-10
        • 2011-09-12
        • 2012-05-11
        • 1970-01-01
        • 2017-03-05
        • 1970-01-01
        • 2011-06-23
        相关资源
        最近更新 更多