DbContext保存多个表项失败



我试图通过foreach循环获得存储在数据库中的对象列表,这是我当前的代码:

foreach (var i in ruleset)
{
var currentRule = Rule;
currentRule.OriginIP = i[0];
currentRule.DestinationIP = i[1];
currentRule.Protocol = (Protocol)Enum.Parse(typeof(Models.Protocol), i[2]);
currentRule.Ports = i[3];
_context.Rules.Add(currentRule);
Console.WriteLine(_context.ChangeTracker.DebugView.LongView);
Console.WriteLine(currentRule.RuleID);
}
_context.SaveChanges();

由于某些原因,这实际上只存储列表中的最后一个对象,我在循环之外设置了SaveChanges(),因为我认为这会提高性能。

当我运行这个命令时,我得到如下结果:

rule {RuleID: -2147482647} Added
RuleID: -2147482647 PK Temporary
CreationDate: '26/01/2021 14:16:10'
DestinationIP: '10.232.20.20'
Enabled: 'False'
OriginIP: '192.168.10.10'
Ports: '80, 443'
Protocol: 'TCP'
0
rule {RuleID: -2147482647} Added
RuleID: -2147482647 PK Temporary
CreationDate: '26/01/2021 14:16:10'
DestinationIP: '10.232.20.21' Originally '10.232.20.20'
Enabled: 'False'
OriginIP: '192.168.10.11' Originally '192.168.10.10'
Ports: '80, 444' Originally '80, 443'
Protocol: 'TCP'

看到ChangeTracker显示每个条目的更改,我试图将SaveChanges()放入循环中,但随后第一个条目被存储,第二个条目出错,因为它试图使用与它刚刚保存的条目相同的ID:

rule {RuleID: -2147482647} Added
RuleID: -2147482647 PK Temporary
CreationDate: '26/01/2021 14:25:40'
DestinationIP: '10.232.20.20'
Enabled: 'False'
OriginIP: '192.168.10.10'
Ports: '80, 443'
Protocol: 'TCP'
62
rule {RuleID: 62} Added
RuleID: 62 PK
CreationDate: '26/01/2021 14:25:40'
DestinationIP: '10.232.20.21' Originally '10.232.20.20'
Enabled: 'False'
OriginIP: '192.168.10.11' Originally '192.168.10.10'
Ports: '80, 444' Originally '80, 443'
Protocol: 'TCP'

我知道我一定做错了什么,但我找不到什么!

var currentRule = Rule;
_context.Rules.Add(currentRule);

不断地添加相同的Rule对象。

当你向EF中添加某物时,它会跟踪该对象。这就是EF知道实体何时被更新的方式。EF无法多次跟踪同一个内存对象并假装它们是不同的。

第一次,你的实体被添加。
第二次,EF意识到这和之前是同一个对象,因此没有添加任何新的东西——它已经在跟踪这个对象了。

确保你添加了新的对象,例如:

var currentRule = new Rule();
// set some values
_context.Rules.Add(currentRule);

你一遍又一遍地添加相同的规则。试试

foreach (var i in ruleset)
{
var currentRule = new Rule();
currentRule.OriginIP = i[0];
currentRule.DestinationIP = i[1];
currentRule.Protocol = (Protocol)Enum.Parse(typeof(Models.Protocol), i[2]);
currentRule.Ports = i[3];
_context.Rules.Add(currentRule);
}
_context.SaveChanges();

最新更新