0

在一个.Net framework项目中,我添加了一个EF 6.x DbContext Generatorusing Visual Studio,它添加了一个.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作为主键,trigger并且sequence将为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)。

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

任何帮助将不胜感激。

4

1 回答 1

0

感谢David Browne在第一篇文章中的评论并使用这个Nuget 包,我只是将文件中主键列StoredGeneratedPattern更改为。 Identity.edmx

通过此更改,实体框架将不会将插入 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.
}
于 2018-11-17T07:30:16.110 回答