Skip to content

Commit

Permalink
Switch to long identity seed
Browse files Browse the repository at this point in the history
Fixes #24840
  • Loading branch information
AndriySvyryd committed Jun 3, 2021
1 parent c09204f commit 1e974b3
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,12 @@ protected override bool IsHandledByConvention(IModel model, IAnnotation annotati
switch (strategy)
{
case SqlServerValueGenerationStrategy.IdentityColumn:
var seed = GetAndRemove<int?>(annotations, SqlServerAnnotationNames.IdentitySeed) ?? 1;
var seed = GetAndRemove<long?>(annotations, SqlServerAnnotationNames.IdentitySeed) ?? 1;
var increment = GetAndRemove<int?>(annotations, SqlServerAnnotationNames.IdentityIncrement) ?? 1;
return new(
onModel
? nameof(SqlServerModelBuilderExtensions.UseIdentityColumns)
: nameof(SqlServerPropertyBuilderExtensions.UseIdentityColumn),
? "UseIdentityColumns"
: "UseIdentityColumn",
(seed, increment) switch
{
(1, 1) => Array.Empty<object>(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static bool CanSetHiLoSequence(
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static ModelBuilder UseIdentityColumns(
this ModelBuilder modelBuilder,
int seed = 1,
long seed = 1,
int increment = 1)
{
Check.NotNull(modelBuilder, nameof(modelBuilder));
Expand Down Expand Up @@ -136,7 +136,7 @@ public static ModelBuilder UseIdentityColumns(
/// </returns>
public static IConventionModelBuilder? HasIdentityColumnSeed(
this IConventionModelBuilder modelBuilder,
int? seed,
long? seed,
bool fromDataAnnotation = false)
{
if (modelBuilder.CanSetIdentityColumnSeed(seed, fromDataAnnotation))
Expand All @@ -157,7 +157,7 @@ public static ModelBuilder UseIdentityColumns(
/// <returns> <see langword="true" /> if the given value can be set as the seed for SQL Server IDENTITY. </returns>
public static bool CanSetIdentityColumnSeed(
this IConventionModelBuilder modelBuilder,
int? seed,
long? seed,
bool fromDataAnnotation = false)
{
Check.NotNull(modelBuilder, nameof(modelBuilder));
Expand Down
8 changes: 4 additions & 4 deletions src/EFCore.SqlServer/Extensions/SqlServerModelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,17 @@ public static void SetHiLoSequenceSchema(this IMutableModel model, string? value
/// </summary>
/// <param name="model"> The model. </param>
/// <returns> The default identity seed. </returns>
public static int GetIdentitySeed(this IReadOnlyModel model)
public static long GetIdentitySeed(this IReadOnlyModel model)
=> model is RuntimeModel
? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData)
: (int?)model[SqlServerAnnotationNames.IdentitySeed] ?? 1;
: (long?)model[SqlServerAnnotationNames.IdentitySeed] ?? 1;

/// <summary>
/// Sets the default identity seed.
/// </summary>
/// <param name="model"> The model. </param>
/// <param name="seed"> The value to set. </param>
public static void SetIdentitySeed(this IMutableModel model, int? seed)
public static void SetIdentitySeed(this IMutableModel model, long? seed)
=> model.SetOrRemoveAnnotation(
SqlServerAnnotationNames.IdentitySeed,
seed);
Expand All @@ -143,7 +143,7 @@ public static void SetIdentitySeed(this IMutableModel model, int? seed)
/// <param name="seed"> The value to set. </param>
/// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
/// <returns> The configured value. </returns>
public static int? SetIdentitySeed(this IConventionModel model, int? seed, bool fromDataAnnotation = false)
public static long? SetIdentitySeed(this IConventionModel model, long? seed, bool fromDataAnnotation = false)
{
model.SetOrRemoveAnnotation(
SqlServerAnnotationNames.IdentitySeed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public static bool CanSetHiLoSequence(
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static PropertyBuilder UseIdentityColumn(
this PropertyBuilder propertyBuilder,
int seed = 1,
long seed = 1,
int increment = 1)
{
Check.NotNull(propertyBuilder, nameof(propertyBuilder));
Expand All @@ -152,7 +152,7 @@ public static PropertyBuilder UseIdentityColumn(
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static PropertyBuilder<TProperty> UseIdentityColumn<TProperty>(
this PropertyBuilder<TProperty> propertyBuilder,
int seed = 1,
long seed = 1,
int increment = 1)
=> (PropertyBuilder<TProperty>)UseIdentityColumn((PropertyBuilder)propertyBuilder, seed, increment);

Expand All @@ -168,7 +168,7 @@ public static PropertyBuilder<TProperty> UseIdentityColumn<TProperty>(
/// </returns>
public static IConventionPropertyBuilder? HasIdentityColumnSeed(
this IConventionPropertyBuilder propertyBuilder,
int? seed,
long? seed,
bool fromDataAnnotation = false)
{
if (propertyBuilder.CanSetIdentityColumnSeed(seed, fromDataAnnotation))
Expand All @@ -189,7 +189,7 @@ public static PropertyBuilder<TProperty> UseIdentityColumn<TProperty>(
/// <returns> <see langword="true" /> if the given value can be set as the seed for SQL Server IDENTITY. </returns>
public static bool CanSetIdentityColumnSeed(
this IConventionPropertyBuilder propertyBuilder,
int? seed,
long? seed,
bool fromDataAnnotation = false)
{
Check.NotNull(propertyBuilder, nameof(propertyBuilder));
Expand Down
28 changes: 18 additions & 10 deletions src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,18 +204,19 @@ public static void SetHiLoSequenceSchema(this IMutableProperty property, string?
/// </summary>
/// <param name="property"> The property. </param>
/// <returns> The identity seed. </returns>
public static int? GetIdentitySeed(this IReadOnlyProperty property)
public static long? GetIdentitySeed(this IReadOnlyProperty property)
=> property is RuntimeProperty
? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData)
: (int?)property[SqlServerAnnotationNames.IdentitySeed];
: (long?)property[SqlServerAnnotationNames.IdentitySeed]
?? property.DeclaringEntityType.Model.GetIdentitySeed();

/// <summary>
/// Returns the identity seed.
/// </summary>
/// <param name="property"> The property. </param>
/// <param name="storeObject"> The identifier of the store object. </param>
/// <returns> The identity seed. </returns>
public static int? GetIdentitySeed(this IReadOnlyProperty property, in StoreObjectIdentifier storeObject)
public static long? GetIdentitySeed(this IReadOnlyProperty property, in StoreObjectIdentifier storeObject)
{
if (property is RuntimeProperty)
{
Expand All @@ -225,18 +226,21 @@ public static void SetHiLoSequenceSchema(this IMutableProperty property, string?
var annotation = property.FindAnnotation(SqlServerAnnotationNames.IdentitySeed);
if (annotation != null)
{
return (int?)annotation.Value;
return (long?)annotation.Value;
}

return property.FindSharedStoreObjectRootProperty(storeObject)?.GetIdentitySeed(storeObject);
var sharedProperty = property.FindSharedStoreObjectRootProperty(storeObject);
return sharedProperty == null
? property.DeclaringEntityType.Model.GetIdentitySeed()
: sharedProperty.GetIdentitySeed(storeObject);
}

/// <summary>
/// Sets the identity seed.
/// </summary>
/// <param name="property"> The property. </param>
/// <param name="seed"> The value to set. </param>
public static void SetIdentitySeed(this IMutableProperty property, int? seed)
public static void SetIdentitySeed(this IMutableProperty property, long? seed)
=> property.SetOrRemoveAnnotation(
SqlServerAnnotationNames.IdentitySeed,
seed);
Expand All @@ -248,9 +252,9 @@ public static void SetIdentitySeed(this IMutableProperty property, int? seed)
/// <param name="seed"> The value to set. </param>
/// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
/// <returns> The configured value. </returns>
public static int? SetIdentitySeed(
public static long? SetIdentitySeed(
this IConventionProperty property,
int? seed,
long? seed,
bool fromDataAnnotation = false)
{
property.SetOrRemoveAnnotation(
Expand All @@ -277,7 +281,8 @@ public static void SetIdentitySeed(this IMutableProperty property, int? seed)
public static int? GetIdentityIncrement(this IReadOnlyProperty property)
=> property is RuntimeProperty
? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData)
: (int?)property[SqlServerAnnotationNames.IdentityIncrement];
: (int?)property[SqlServerAnnotationNames.IdentityIncrement]
?? property.DeclaringEntityType.Model.GetIdentityIncrement();

/// <summary>
/// Returns the identity increment.
Expand All @@ -298,7 +303,10 @@ public static void SetIdentitySeed(this IMutableProperty property, int? seed)
return (int?)annotation.Value;
}

return property.FindSharedStoreObjectRootProperty(storeObject)?.GetIdentityIncrement(storeObject);
var sharedProperty = property.FindSharedStoreObjectRootProperty(storeObject);
return sharedProperty == null
? property.DeclaringEntityType.Model.GetIdentityIncrement()
: sharedProperty.GetIdentityIncrement(storeObject);
}

/// <summary>
Expand Down
50 changes: 39 additions & 11 deletions test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ public virtual void Model_use_identity_columns()
modelBuilder
.HasAnnotation(""Relational:MaxIdentifierLength"", 128)
.HasAnnotation(""SqlServer:IdentityIncrement"", 1)
.HasAnnotation(""SqlServer:IdentitySeed"", 1)
.HasAnnotation(""SqlServer:IdentitySeed"", 1L)
.HasAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.IdentityColumn);"),
o =>
{
Expand All @@ -727,7 +727,7 @@ public virtual void Model_use_identity_columns_custom_seed()
modelBuilder
.HasAnnotation(""Relational:MaxIdentifierLength"", 128)
.HasAnnotation(""SqlServer:IdentityIncrement"", 1)
.HasAnnotation(""SqlServer:IdentitySeed"", 5)
.HasAnnotation(""SqlServer:IdentitySeed"", 5L)
.HasAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.IdentityColumn);"),
o =>
{
Expand All @@ -748,7 +748,7 @@ public virtual void Model_use_identity_columns_custom_increment()
modelBuilder
.HasAnnotation(""Relational:MaxIdentifierLength"", 128)
.HasAnnotation(""SqlServer:IdentityIncrement"", 5)
.HasAnnotation(""SqlServer:IdentitySeed"", 1)
.HasAnnotation(""SqlServer:IdentitySeed"", 1L)
.HasAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.IdentityColumn);"),
o =>
{
Expand All @@ -763,20 +763,48 @@ public virtual void Model_use_identity_columns_custom_increment()
public virtual void Model_use_identity_columns_custom_seed_increment()
{
Test(
builder => builder.UseIdentityColumns(5, 5),
builder => {
builder.UseIdentityColumns(long.MaxValue, 5);
builder.Entity(
"Building", b =>
{
b.Property<int>("Id");

b.HasKey("Id");

b.ToTable("Buildings");
});
},
AddBoilerPlate(
@"
modelBuilder
.HasAnnotation(""Relational:MaxIdentifierLength"", 128)
.HasAnnotation(""SqlServer:IdentityIncrement"", 5)
.HasAnnotation(""SqlServer:IdentitySeed"", 5)
.HasAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.IdentityColumn);"),
.HasAnnotation(""SqlServer:IdentitySeed"", 9223372036854775807L)
.HasAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity(""Building"", b =>
{
b.Property<int>(""Id"")
.ValueGeneratedOnAdd()
.HasColumnType(""int"")
.HasAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.IdentityColumn);
b.HasKey(""Id"");
b.ToTable(""Buildings"");
});"),
o =>
{
Assert.Equal(4, o.GetAnnotations().Count());
Assert.Equal(SqlServerValueGenerationStrategy.IdentityColumn, o.GetValueGenerationStrategy());
Assert.Equal(5, o.GetIdentitySeed());
Assert.Equal(long.MaxValue, o.GetIdentitySeed());
Assert.Equal(5, o.GetIdentityIncrement());

var property = o.FindEntityType("Building").FindProperty("Id");
Assert.Equal(SqlServerValueGenerationStrategy.IdentityColumn, property.GetValueGenerationStrategy());
Assert.Equal(long.MaxValue, property.GetIdentitySeed());
Assert.Equal(5, property.GetIdentityIncrement());
});
}

Expand Down Expand Up @@ -3314,7 +3342,7 @@ public virtual void Property_with_identity_column()
.ValueGeneratedOnAdd()
.HasColumnType(""int"")
.HasAnnotation(""SqlServer:IdentityIncrement"", 1)
.HasAnnotation(""SqlServer:IdentitySeed"", 1)
.HasAnnotation(""SqlServer:IdentitySeed"", 1L)
.HasAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.IdentityColumn);
b.HasKey(""Id"");
Expand Down Expand Up @@ -3354,7 +3382,7 @@ public virtual void Property_with_identity_column_custom_seed()
.ValueGeneratedOnAdd()
.HasColumnType(""int"")
.HasAnnotation(""SqlServer:IdentityIncrement"", 1)
.HasAnnotation(""SqlServer:IdentitySeed"", 5)
.HasAnnotation(""SqlServer:IdentitySeed"", 5L)
.HasAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.IdentityColumn);
b.HasKey(""Id"");
Expand Down Expand Up @@ -3394,7 +3422,7 @@ public virtual void Property_with_identity_column_custom_increment()
.ValueGeneratedOnAdd()
.HasColumnType(""int"")
.HasAnnotation(""SqlServer:IdentityIncrement"", 5)
.HasAnnotation(""SqlServer:IdentitySeed"", 1)
.HasAnnotation(""SqlServer:IdentitySeed"", 1L)
.HasAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.IdentityColumn);
b.HasKey(""Id"");
Expand Down Expand Up @@ -3433,7 +3461,7 @@ public virtual void Property_with_identity_column_custom_seed_increment()
.ValueGeneratedOnAdd()
.HasColumnType(""int"")
.HasAnnotation(""SqlServer:IdentityIncrement"", 5)
.HasAnnotation(""SqlServer:IdentitySeed"", 5)
.HasAnnotation(""SqlServer:IdentitySeed"", 5L)
.HasAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.IdentityColumn);
b.HasKey(""Id"");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public void GenerateFluentApi_IModel_works_with_identity()

Assert.Collection(
result.Arguments,
seed => Assert.Equal(5, seed),
seed => Assert.Equal(5L, seed),
increment => Assert.Equal(10, increment));
}

Expand All @@ -191,7 +191,7 @@ public void GenerateFluentApi_IProperty_works_with_identity()

Assert.Collection(
result.Arguments,
seed => Assert.Equal(5, seed),
seed => Assert.Equal(5L, seed),
increment => Assert.Equal(10, increment));
}

Expand Down

0 comments on commit 1e974b3

Please sign in to comment.