在保存记录之前如何使用 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 完成获取和分配键值的繁重工作要容易得多。
我是 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 完成获取和分配键值的繁重工作要容易得多。