StronglyTypedId icon indicating copy to clipboard operation
StronglyTypedId copied to clipboard

EF Value Generator for int and long backed Id's

Open kazeshini178 opened this issue 1 year ago • 5 comments

This could be useful for identity columns in SQL databases. Not sure if this should potentially be treated as its own generator, currently just extended the templates for the EF Int and Long converters.

Sample usage when configuring EF Tables

 modelBuilder
        .Entity<Entity>(builder =>
        {
            builder
                .Property(x => x.Id)
                .HasConversion(new EntityId.EfCoreValueConverter())
                .HasValueGenerator<EntityId.EfCoreValueGenerator>()
                .ValueGeneratedOnAdd();
        });

kazeshini178 avatar Aug 13 '22 23:08 kazeshini178

I like the idea behind this, but the implementation is a bit problematic, I think. Currently, it has race conditions as it's not thread safe. It also won't work in a server farm scenario (one of the reasons I'm not a fan of sequential IDs!).🤔

However, I'm not sure exactly how this is supposed to work? I'm a bit torn how to proceed, this would be very useful for e.g. the Guid IDs, but I'm not sure if it really works for the int/long versions?

andrewlock avatar Aug 23 '22 21:08 andrewlock

Status on this? Or is it abandoned?

Rudde avatar Sep 03 '22 18:09 Rudde

Hi @Rudde sorry no haven't abandon this from my end. Just had a few busy weekends :D

Currently, it has race conditions as it's not thread safe. It also won't work in a server farm scenario (one of the reasons I'm not a fan of sequential IDs!).🤔

Been doing a bit more research into EF, seems it should be thread safe as long as each thread uses it own DbContext though for the cases where a singleton context is used for multiple threads we could use:

 System.Threading.Interlocked.Increment(ref _id);

Implement would then be similar to the internal EF Value generator which might be better. Internal Long Generator

For the case of server farms, not sure if there would be an issue as the Generator only generates temporary values. The SQL Server is responsible for the final generated value, this value would be used by EF to know which entity it should assign the "real" ID back too.

However, I'm not sure exactly how this is supposed to work? I'm a bit torn how to proceed, this would be very useful for e.g. the Guid IDs, but I'm not sure if it really works for the int/long versions?

For int/long it helps prevent the an issue where inserting multiple entity all have an internal value of 0. From some the project been working on with StronglyTypedId as well as this issue #59 I came across.

Happy to add one for Guid as well, think the only difference would be that it wouldn't generate a temp value like the int/long ones.

Though for Guid I found public EntityId Id { get; set; } = EntityId.New(); works pretty well for Guid types, but this would give people options 😄

Hope this help @andrewlock

kazeshini178 avatar Sep 04 '22 18:09 kazeshini178

Won't this still have a race condition if you run several API instances? Isn't it it best to let the database increment the value, like it does on regular ints, or isn't this possible to configure? I understand it probably will be slightly different for each underlying sql driver supported

Rudde avatar Sep 04 '22 22:09 Rudde

This would still let SQL increment/generate the int/long ID's. This would just allow for EF to track which entity should get which ID in the case that multiple entities are added at once.

kazeshini178 avatar Sep 05 '22 12:09 kazeshini178