我试图在同一请求和控制器中添加同一对象的两个实例。我觉得这是一个相当普遍的操作,但是EF Core似乎对此有问题。我正在研究一个会计系统,您始终记录2次交易。
private void AddLedgersForTrade(Trade trade)
{
decimal TradeTranFee = 0;
decimal ForTranFee = 0;
if(trade.TradeCoinId == trade.FeeCoinId){
TradeTranFee = trade.Fee;
} else {
ForTranFee = trade.Fee;
}
var ledger1 = new LedgerTransaction{
TransactionId = trade.TransactionId,
TransactionDate = trade.TradeDate,
ExchangeId = trade.FromExchangeId,
CoinId = trade.TradeCoinId,
Amount = trade.TradeAmount * -1,
ExchangeRate = 1,
Fee = TradeTranFee,
LastUpdate = trade.LastUpdate,
TradeId = trade.Id,
Owner = trade.Owner
};
var ledger2 = new LedgerTransaction{
TransactionId = trade.TransactionId,
TransactionDate = trade.TradeDate,
ExchangeId = trade.ToExchangeId,
CoinId = trade.ForCoinId,
Amount = trade.ForAmount,
ExchangeRate = trade.ExchangeRate,
Fee = ForTranFee,
LastUpdate = trade.LastUpdate,
TradeId = trade.Id,
Owner = trade.Owner
};
ledgerRepository.AddLedgerTransaction(ledger1);
ledgerRepository.AddLedgerTransaction(ledger2);
}
第一个工作正常,但是一旦尝试添加第二笔交易,我就会得到错误:
system.invalidoperationException:无法跟踪实体类型" LEDGERTRANSACTION"的实例,因为另一个带有键值'id:0'的实例已经在跟踪。连接现有实体时,请确保仅附有一个具有给定键值的实体实例。 在Microsoft.entityFrameworkcore.changetracking.internal.indernitymap`1.Add(tkey键,internalTityEntry条目)....
我的上下文是为:
设置的modelBuilder.Entity<LedgerTransaction>(entity =>
{
entity.HasIndex(e => e.CoinId);
entity.HasIndex(e => e.ExchangeId);
entity.HasIndex(e => e.IsManual);
entity.HasIndex(e => e.Owner);
entity.HasIndex(e => e.TradeId);
entity.Property(e => e.Id).ValueGeneratedNever();
entity.Property(e => e.ExchangeId).HasDefaultValueSql("'0'");
entity.Property(e => e.IsManual).HasDefaultValueSql("'b\'0\''");
entity.Property(e => e.LastUpdate).HasDefaultValueSql("'0001-01-01 00:00:00'");
});
我读到这可能是EF Core 2.0.x中的错误,但我茫然。我尝试将Asnotracking()添加到我最初的"交易"实体的查询中,但仍然存在相同的问题。有趣的是,我是从代码优先的EF项目开始的,但是随后脚手架数据库并获得了数据库 - 第一。用代码优先的方法正常工作。我猜这一定是在某个地方的上下文。
也许您已经设置了(摘要中缺少)
builder.Entity<Ledger>().HasKey(e => e.Id);
但省略了
builder.Entity<Ledger>().Property(e => e.Id).ValueGeneratedOnAdd();
,而且,为了避免头痛,如果需要在同一db的两个实例之间合并,我将使 Id
a Guid
而不是 int
。