在保存记录之前如何使用 Entity Framework(v5) 获取标识值

How do I get an identity value with Entity Framework(v5) before I save the record

我是 entity framework 的新手,我一直在寻找这个问题的答案,但我找不到任何可以直接解决这个问题的东西。

问题来了。我在 Oracle 中有一个 table。在这个 table 中有 2 个字段(还有更多但对这个问题不重要)。 Card_Transaction_Id 和 Parent_Card_Transaction_ID。 Parent_Card_Transaction_Id 字段受 Card_Transaction_Id 字段约束,我通过触发器使用 Oracle 序列来填充 Card_Transaction_Id 字段。

在我的代码中,我使用 Entity Framework(版本 5)通过代码优先方法进行连接。

问题出在我尝试创建新记录时。我需要知道下一个序列值是什么才能填充 Parent_Card_Transaction_Id。我的卡交易映射:

public class CardTransactionMap : EntityTypeConfiguration<CardTransaction>
{
    public CardTransactionMap(string schema)
    {

        ToTable("CARD_TRANSACTION", schema);

        // Mappings & Properties

        // Primary Key
        HasKey(t => t.CardTransactionId);
        Property(t => t.CardTransactionId)
            .HasColumnName("CARD_TRANSACTION_ID")
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        Property(t => t.ParentCardTransactionId)
            .HasColumnName("PARENT_CARD_TRANSACTION_ID");

        Property(t => t.CardProfileId)
            .HasColumnName("CARD_PROFILE_ID");
    }
}

问题是 - 在我保存记录之前有没有办法得到下一个序列号?

我目前的工作是使用以下方法:

    public static decimal GetNextCardTransactionSequenceValue()
    {
        using (var context = new Context(new OracleConnectionFactory().GetConnection()))
        {

            var sequence = context.Database.SqlQuery<int>("select card_transaction_id from card_transaction").ToList();

            return sequence[0];

        }   

    }

使用该方法,我得到下一个值,然后填充我的 table。这行得通,但我不喜欢这样做。我觉得必须有更好的方法来做到这一点。

提前致谢。

创建一个存储过程或查询,它将return你Table的下一个值这里是一个例子

SELECT NVL(MAX(card_transaction_id + 1), 0) AS MAX_VAL
FROM card_transaction T;

或创建触发器 - 用于 OracleDB

将您的 table 定义更改为:

CREATE TABLE t1 (c1 NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY, 
               c2 VARCHAR2(10));

根据我在评论中提供的 link 中的信息。 更新后ef会自动查询插入的id的值,不需要填写插入前的id。 ef 将生成一个没有 id.

的插入 sql 查询

必须通过导航属性执行此操作。

通过在同一会话中实际使用序列之前获取序列中的下一个值,您自己创建了一个并发问题:另一个用户可以增加索引(通过插入)从绘制下一个值到将其分配给 child 记录之间的时间。现在 child 将属于其他用户的记录!

如果您的 CardTransaction class 有这样的 parent 引用:

int ParentCardTransaction { get; set; }

[ForeignKey("ParentCardTransaction")]
CardTransaction ParentCardTransaction { get; set; }

您可以一次性创建 parent 和 child 并调用 SaveChanges 而无需担心自己设置 FK 值:

var parent = new CardTransaction { ... };
var child = new CardTransaction { ParentCardTransaction = parent, ... };
SaveChanges();

现在 EF 将从 parent 获取新的 CardTransactionId 并将其分配给 child 的 FK。因此生成和获取 parent ID 全部发生在一个会话 中,因此它保证是相同的值。

除了防止并发问题,当然,让 EF 完成获取和分配键值的繁重工作要容易得多。