Tomas Aschan
Tomas Aschan

Reputation: 60564

EF Core won't let me add multiple new entities of the same type

I have the following entities and 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)
    {
    }
}

and the following test code:

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);
}

This throws an InvalidOperationException:

The instance of entity type 'Bar' cannot be tracked because another instance with the key value 'BarId:0' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

I understand from the error message that this won't work, but how do I work around it? How do I, when I'm not building the entities manually but rather using AutoFixture (and thus have less granular control of their initialization)?

Upvotes: 0

Views: 835

Answers (1)

MateuszWkDev
MateuszWkDev

Reputation: 515

It does'nt work because when you add new foo with new bar. New bar have assigned 0 because this is default int. So when you add them to context you have 2 entities with id=0. BarId is key column so this is not allowed. Specify diffrent ids:

    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);
    }

Or use:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

on barId.

Upvotes: 3

Related Questions