Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EF Core 3.0 In Memory DB Set Primary Key Next Rec Id #18187

Closed
aherrick opened this issue Oct 2, 2019 · 5 comments
Closed

EF Core 3.0 In Memory DB Set Primary Key Next Rec Id #18187

aherrick opened this issue Oct 2, 2019 · 5 comments
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported

Comments

@aherrick
Copy link

aherrick commented Oct 2, 2019

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

@ajcvickers
Copy link
Contributor

@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?

@aherrick
Copy link
Author

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

@ajcvickers
Copy link
Contributor

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

@aherrick
Copy link
Author

its already posted above :)

@ajcvickers
Copy link
Contributor

@aherrick Changing your code as follows works for me:

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

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

@ajcvickers ajcvickers added closed-no-further-action The issue is closed and no further action is planned. and removed type-bug labels Oct 21, 2019
@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported
Projects
None yet
Development

No branches or pull requests

2 participants