Efcore: EF Core 3.0 In Memory DB Set Primary Key Next Rec Id

Created on 2 Oct 2019  路  5Comments  路  Source: dotnet/efcore

In EF Core 2.2 In Memory DB we forced our next primary key using a method like this:

        public static void SetNextIdValueForTable(this DbContext context, Type tableType, int forcedNextIdValue = 0)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var cache = context.GetService<IValueGeneratorCache>();

            // We calculate what should be one less than the next ID value by taking the given value for ID and subtracting one if given
            // or we calculate the number of records already in the given table.
            var oneLessThanNextIdValue = forcedNextIdValue > 0
                ? forcedNextIdValue - 1
                : context.Model.GetEntityTypes(tableType).FirstOrDefault()?.GetSeedData().Count();

            foreach (var keyProperty in context.Model.GetEntityTypes(tableType)
                .Select(e => e.FindPrimaryKey().Properties[0])
                .Where(p => p.ClrType == typeof(int)
                            && p.ValueGenerated == ValueGenerated.OnAdd))
            {
                var generator = (ResettableValueGenerator)cache.GetOrAdd(
                    keyProperty,
                    keyProperty.DeclaringEntityType,
                    (_, __) => new ResettableValueGenerator());

                generator.SetNextIdValue(oneLessThanNextIdValue ?? 0);
            }
        }


    public class ResettableValueGenerator : ValueGenerator<int>
    {
        private int current;

        public override bool GeneratesTemporaryValues => false;

        public override int Next(EntityEntry entry)
            => Interlocked.Increment(ref current);

        public void SetNextIdValue(int currentNumOfRecords) => current = currentNumOfRecords;
    }

In 3.0, it doesn't seem to work anymore. Then next record I insert is always PK 1.

Spike code sample:
EFCore3MemorySetRecId.zip

closed-question customer-reported

All 5 comments

@aherrick Given that this was a workaround for issues in-memory value generation which have been fixed in 3.0, can you provide some more details as to why it is that you still need to do this?

we need a way to insert a record into a blank the in memory DB Table with a certain Primary Key.

@aherrick That should work. If it doesn't, then please post a small, runnable project/solution that demonstrates the issue.

its already posted above :)

@aherrick Changing your code as follows works for me:

```C#
// force next student id inserted to be 6
// Not needed: _ctx.SetNextIdValueForTable(typeof(Student), 6);

        _ctx.Students.Add(new Student()
        {
            Id = 6,
            StudentName = "Andrew"
        });

```

Was this page helpful?
0 / 5 - 0 ratings