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

BulkInsert throws exception on shadow primary key #1333

Open
axelgenus opened this issue Nov 28, 2023 · 2 comments
Open

BulkInsert throws exception on shadow primary key #1333

axelgenus opened this issue Nov 28, 2023 · 2 comments

Comments

@axelgenus
Copy link

axelgenus commented Nov 28, 2023

I have a SQL Server table with a primary key which is mapped to EFCore as a shadow property:

builder.Property<Guid>("Id")
  .HasDefaultValueSql("NEWID()")
  .IsRequired();

builder.HasKey("Id");

I am calling BulkInsertAsync like this:

await _repository.BulkInsertAsync(items,
    config =>
    {
        config.BatchSize = 500;
        config.BulkCopyTimeout = 0;

        config.UseOptionLoopJoin = false;
    },
    pct => { _logger.LogDebug("Progress = {Progress:P1}", pct); },
    cancellationToken);

It throws the following exception:

System.Collections.Generic.KeyNotFoundException: The given key 'Id' was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at EFCore.BulkExtensions.TableInfo.LoadData[T](DbContext context, Type type, IEnumerable`1 entities, Boolean loadOnlyPKColumn)
   at EFCore.BulkExtensions.TableInfo.CreateInstance[T](DbContext context, Type type, IEnumerable`1 entities, OperationType operationType, BulkConfig bulkConfig)
   at EFCore.BulkExtensions.DbContextBulkTransaction.ExecuteAsync[T](DbContext context, Type type, IEnumerable`1 entities, OperationType operationType, BulkConfig bulkConfig, Action`1 progress, CancellationToken cancellationToken)
[...]

Enabling EnableShadowProperties and ShadowPropertyValue (to set the primary key on client side instead of relying on the SQL default value) do not change the outcome.

EDIT: I also trying adding config.PropertiesToExclude = ["Id"]; to no avail.

I tried debugging using Rider's decompiler and it seems that the exception is thrown in EFCore.BulkExtensions' TableInfo.cs at line 354 (link).

Looking at the code, it seems an edge case: GUID primary key + shadow property = exception. I could not figure out what dictionary the exception is talking about since allPropertiesExceptTimeStamp is an IEnumerable.

@axelgenus
Copy link
Author

I am using EFCore.BulkExtensions 8.0 btw.

@axelgenus
Copy link
Author

There are two workarounds for this issue:

  • Define the primary key as a public property and just map it as a usual: builder.HasKey(e => e.Id);.
  • Define the primary key as a private property and map it as a shadow property.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant