使用 Oracle.ManagedDataAccess.EntityFramework 的交易获取插入记录的 ID 时出现问题

Problem in getting inserted record`s ID Using transaction with Oracle.ManagedDataAccess.EntityFramework

在一个 .Net framework 项目中,我使用 visual studio 添加了一个 EF 6.x DbContext Generator,它添加了一个 .edmx 文件,其中包含一些 .tt 文件;实现了我的 database first 结构。

然后我连接到我的 oracle 数据库并将我的表添加到其中,其中包含一些模型,如下所示:

// DatabaseContext.tt > USER_TYPE.cs
public class USER_TYPE
{
    public int ID { get; set; } // have sequence and insert trigger.
    public string NAME { get; set; }
}

// DatabaseContext.tt > USER.cs
public class USER
{
    public int ID { get; set; } // have sequence and insert trigger.
    public int USER_TYPE_ID { get; set; } // foreign key to USER_TYPES.ID
    public string NAME { get; set; }
}

另外 Oracle.ManagedDataAccess.EntityFramework Nuget 包已安装。

两个表都有 ID 作为主键,triggersequence 将为 ID 列提供唯一值。

现在我想开始一个事务以在相关的表中插入一些记录:

using (var db = new DatabaseContext())
using (var transaction = db.Database.BeginTransaction())
{
    // insert userType
    var userType = new USER_TYPE
    {
        NAME = "admin"
    };

    db.USER_TYPES.Add(userType);
    db.SaveChanges();

    // userType.ID == 0 : true

    // insert user
    var user = new USER
    {
        NAME = "admin user",
        USER_TYPE_ID = userType.ID
    };

    db.USERS.Add(user);
    db.SaveChanges();

    transaction.Commit(); 
}

问题是在 db.USER_TYPES.Add(userType); db.SaveChanges() 之后,我们知道 userType.ID 将保持 0(因为我们使用的是 oracle)。

网上有一些解决方案建议通过执行 select 最大 ID 查询来获取最新插入的 ID,或者在插入之前获取下一个序列值。但是当我们使用 Transaction 时,db 中没有实际记录到 select max,或者 selecting 从序列中不准确且含糊。

我们将不胜感激。

感谢 David Browne's comment in the first post and using this Nuget 包,我只是将 StoredGeneratedPattern 更改为 主键列 Identity ] 在我的 .edmx 文件中。

通过此更改,Entity Framework 将不会将插入 sql 脚本中的 ID 传递给数据库:

insert into MY_TABLE (NAME) VALUES (@some_value) -- ID is not passed.

并且在插入之后,ID(我指的是主键列)会自动从数据库中获取,即使我使用transactions

using (var db = new DatabaseContext())
using (var transaction = db.Database.BeginTransaction())
{
    var userType = new USER_TYPE
    {
        NAME = "admin"
    };

    db.USER_TYPES.Add(userType);
    db.SaveChanges();

    Debug.Assert.IsTrue(userType.ID != 0); // ✔️ will be passed.
}