linq2db / linq2db.EntityFrameworkCore

Bring power of Linq To DB to Entity Framework Core projects
MIT License
462 stars 38 forks source link

Bulk Copy does not generate new Ids when inserting #113

Closed Nate129 closed 3 years ago

Nate129 commented 3 years ago

Hi,

I am attempting to use the BulkCopy feature to insert multiple rows into a table while allowing the database to generate the identity column's value. However, it seems that these values are not being generated as a unique constraint violation occurs after the first row is inserted. Configuring BulkCopyOptions' KeepIdentity property (true or false) seems to have no effect.

I created a repository here that contains a test that reproduces the issue.

The issue occurs on the current version of linq2db.EntityFrameworkCore (5.1.4) using EF Core Sqlite as the provider.

MaceWindu commented 3 years ago

Quickly looked at your test - I don't see Identity attribute on Person.Id property. It is required to tell linq2db that this property values could be generated by database and could be skipped on insert.

Nate129 commented 3 years ago

Hi,

The Person.Id property is automatically considered an Identity column with EF Core if it is named Id so there is no need to label it with the Key attribute when only using EF Core. Since Linq2db.EntityFrameworkCore generates its metadata and subsequently Person.Id column's Identity state by converting EF Core's metadata to Linq2db metadata, I expected to not have to explicitly provide the Identity Linq2db attribute in the class as EF Core was already treating it as an Identity column.

Nevertheless, I added the Identity attribute to Person.Id and the test still failed in the same way.

Thank you for your help.

sdanyliv commented 3 years ago

Will check. How about attribute [DatabaseGenerated(DatabaseGeneratedOption.Identity)] ?

Nate129 commented 3 years ago

I just tried that attribute as well, no change in behavior- same unique constraint SQL error.

sdanyliv commented 3 years ago

I had to update mapping reader. If you specify for column builder.Property(x => x.Id).UseIdentityColumn() it should work.

Nate129 commented 3 years ago

I don't have access to a builder already as I'm using DbContext extension methods to get a connection/context. I found a GetFluentMappingBuilder method in the context's MappingSchema, which returns a builder I can use to set the Identity as suggested:

using var linq2dbContext = context.CreateLinqToDbContext();
var builder = linq2dbContext.MappingSchema.GetFluentMappingBuilder();
builder.Entity<Person>().HasIdentity(p => p.Id);

However, I can't seem to find a method I can use to return the builder to the context so I can't confirm your diagnosis via your suggestion currently.

Nevertheless, shouldn't Linq2db already have this configuration set when it converts the EF Core metadata to Linq2db metadata?