diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 5572c51..2d85462 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -5,7 +5,7 @@
enable
latest
true
- 0.3.1
+ 0.3.2
1.0.0
true
true
diff --git a/src/EfOrderBy/Configuration.cs b/src/EfOrderBy/Configuration.cs
index fdfbe58..2880012 100644
--- a/src/EfOrderBy/Configuration.cs
+++ b/src/EfOrderBy/Configuration.cs
@@ -8,7 +8,20 @@ sealed class Configuration(Type elementType)
static readonly ConcurrentDictionary cache = new();
internal static void Cache(Type entityType, Configuration configuration)
- => cache[entityType] = configuration;
+ => cache.AddOrUpdate(
+ entityType,
+ configuration,
+ (type, existing) =>
+ {
+ if (!existing.ClauseMetadataList.SequenceEqual(configuration.ClauseMetadataList))
+ {
+ throw new InvalidOperationException(
+ $"Conflicting default ordering configurations for entity type '{type.Name}'. " +
+ $"When multiple DbContext types share the same entity, they must configure the same default ordering.");
+ }
+
+ return existing;
+ });
internal static Configuration? TryGet(Type entityType)
=> cache.GetValueOrDefault(entityType);
diff --git a/src/Tests/DuplicateOrderByTests.cs b/src/Tests/DuplicateOrderByTests.cs
index 73468e9..709524d 100644
--- a/src/Tests/DuplicateOrderByTests.cs
+++ b/src/Tests/DuplicateOrderByTests.cs
@@ -132,6 +132,20 @@ public class AnotherDuplicateTestEntity
public string Value { get; set; } = "";
}
+public class ThenByEntity
+{
+ public int Id { get; set; }
+ public string Name { get; set; } = "";
+ public int Priority { get; set; }
+}
+
+public class ThenByDescEntity
+{
+ public int Id { get; set; }
+ public string Name { get; set; } = "";
+ public int Priority { get; set; }
+}
+
#endregion
#region Test Contexts - Each with unique configuration
@@ -186,20 +200,20 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
public class OrderByWithThenByContext(DbContextOptions options) : DbContext(options)
{
- public DbSet Entities => Set();
+ public DbSet Entities => Set();
protected override void OnModelCreating(ModelBuilder modelBuilder) =>
- modelBuilder.Entity()
+ modelBuilder.Entity()
.OrderBy(_ => _.Name)
.ThenBy(_ => _.Priority); // Correct usage
}
public class OrderByDescWithThenByDescContext(DbContextOptions options) : DbContext(options)
{
- public DbSet Entities => Set();
+ public DbSet Entities => Set();
protected override void OnModelCreating(ModelBuilder modelBuilder) =>
- modelBuilder.Entity()
+ modelBuilder.Entity()
.OrderByDescending(_ => _.Name)
.ThenByDescending(_ => _.Priority); // Correct usage
}
diff --git a/src/Tests/MigrationTests.cs b/src/Tests/MigrationTests.cs
index 32a2e33..9b7729f 100644
--- a/src/Tests/MigrationTests.cs
+++ b/src/Tests/MigrationTests.cs
@@ -105,4 +105,59 @@ public void DesignTimeModelHasNoConfigurationAnnotations()
Assert.That(designTimeModel.FindAnnotation("DefaultOrderBy:InterceptorRegistered"), Is.Null);
Assert.That(designTimeModel.FindAnnotation("DefaultOrderBy:IndexCreationDisabled"), Is.Null);
}
+
+ [Test]
+ public void ConflictingOrderingAcrossContexts_Throws()
+ {
+ // First context configures SharedEntity with OrderBy(Name)
+ var options1 = new DbContextOptionsBuilder()
+ .UseSqlServer("Server=.;Database=Test;Trusted_Connection=True")
+ .UseDefaultOrderBy()
+ .Options;
+
+ using (var context = new ContextWithNameOrdering(options1))
+ {
+ _ = context.Model;
+ }
+
+ // Second context configures SharedEntity with OrderByDescending(Value) - should throw
+ var options2 = new DbContextOptionsBuilder()
+ .UseSqlServer("Server=.;Database=Test;Trusted_Connection=True")
+ .UseDefaultOrderBy()
+ .Options;
+
+ var exception = Assert.Throws(() =>
+ {
+ using var context = new ContextWithValueOrdering(options2);
+ _ = context.Model;
+ });
+
+ Assert.That(exception!.Message, Does.Contain("SharedEntity"));
+ Assert.That(exception.Message, Does.Contain("Conflicting"));
+ }
+}
+
+public class SharedEntity
+{
+ public int Id { get; set; }
+ public string Name { get; set; } = "";
+ public string Value { get; set; } = "";
+}
+
+class ContextWithNameOrdering(DbContextOptions options) : DbContext(options)
+{
+ public DbSet Entities => Set();
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder) =>
+ modelBuilder.Entity()
+ .OrderBy(_ => _.Name);
+}
+
+class ContextWithValueOrdering(DbContextOptions options) : DbContext(options)
+{
+ public DbSet Entities => Set();
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder) =>
+ modelBuilder.Entity()
+ .OrderByDescending(_ => _.Value);
}
diff --git a/src/Tests/RequireOrderingTests.cs b/src/Tests/RequireOrderingTests.cs
index 907b619..4cdeba9 100644
--- a/src/Tests/RequireOrderingTests.cs
+++ b/src/Tests/RequireOrderingTests.cs
@@ -113,9 +113,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
- // All entities have ordering configured
+ // All entities have ordering configured (must match TestDbContext's ordering)
modelBuilder.Entity()
- .OrderBy(_ => _.CreatedDate);
+ .OrderByDescending(_ => _.CreatedDate);
}
}