Search code examples
.netin-memory-databaseef-core-2.2

How to get EFCore In-memory db to auto-increment non-key fields


We have an entity keyed on a guid with another human-readable key based on an auto-incrementing int property. This works as expected when running the app.

For testing purposes we are using an EF in-memory database but this only seems to auto-increment a column if it also also a key.

Using either the property annotation attribute or the fluent API has no effect.

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int OrderNumber { get; private set; }

    ===========

    modelBuilder.Entity<Order>(order =>
    {
        order.Property(p => p.OrderNumber).ValueGeneratedOnAdd();
    });

In both cases OrderNumber is left as 0 after insert. Is there any way of getting the in-memory db to do this, or is this a known limitation? (Googling has uncovered issues around re-seeding of key values, but not this particular issue)


Solution

  • Value generation of non key properties works differently (don't know why) - it's not triggered when the property has no explicit value generator assigned. For providers that generated temporary keys it works because the actual value is assigned after SaveChanges. But in-memory provider value generators generate persistent keys, and since they are not called for non key properties, ValueGeneratedOnAdd has no effect (doesn't work).

    The workaround is to explicitly assign value generator for such properties. You'd need the following namespace:

    using Microsoft.EntityFrameworkCore.InMemory.ValueGeneration.Internal;
    

    and then a code similar to this:

    modelBuilder.Entity<Order>(order =>
    {
        var orderNumber = order.Property(p => p.OrderNumber);
        orderNumber.ValueGeneratedOnAdd();
        // only for in-memory
        if (Database.IsInMemory())
            orderNumber.HasValueGenerator<InMemoryIntegerValueGenerator<int>>();
    });