我有以下实体和DbContext:
public class Foo
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int FooId { get; set; }
public Bar Bar { get; set; }
}
public class Bar
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int BarId { get; set; }
public string Baz { get; set; }
}
public class ReproContext : DbContext
{
public DbSet<Foo> Foos { get; set; }
public DbSet<Bar> Bars { get; set; }
public ReproContext(DbContextOptions<ReproContext> options) : base(options)
{
}
}
以及以下测试代码:
using (var context = new ReproContext(new DbContextOptionsBuilder<ReproContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString("D"))
.EnableSensitiveDataLogging()
.Options))
{
var foos = new[]
{
new Foo {Bar = new Bar {Baz = "1"}},
new Foo {Bar = new Bar {Baz = "2"}}
};
context.Foos.AddRange(foos);
}
这会引发InvalidOperationException
:
无法跟踪实体类型“Bar”的实例,因为已经跟踪了另一个键值为“BarId:0”的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。
我从错误消息中了解到这不起作用,但我该如何解决呢?当我不是手动构建实体而是使用AutoFixture(因此对其初始化的控制较少)时,我该怎么办?
答案 0 :(得分:3)
它不起作用,因为当你用新栏添加新的foo时。新栏已分配0,因为这是默认的int。因此,当您将它们添加到上下文时,您有2个id = 0的实体。 BarId是关键列,因此不允许这样做。 指定不同的ID:
using (var context = new ReproContext(new DbContextOptionsBuilder<ReproContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString("D"))
.EnableSensitiveDataLogging()
.Options))
{
var foos = new[]
{
new Foo {Bar = new Bar {Baz = "1", BarId = 1}},
new Foo {Bar = new Bar {Baz = "2", BarId = 2}}
};
context.Foos.AddRange(foos);
}
或使用:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
on barId。