Skip to content

Commit fd69bdc

Browse files
committed
Added test for collection handling in temp table creator.
1 parent d8aab67 commit fd69bdc

File tree

4 files changed

+57
-12
lines changed

4 files changed

+57
-12
lines changed

src/Thinktecture.EntityFrameworkCore.SqlServer/EntityFrameworkCore/TempTables/SqlServerTempTableCreator.cs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -236,17 +236,16 @@ private string GetColumnsDefinitions(SqlServerTempTableCreatorCacheKey options)
236236
if (_stringColumnTypes.Any(t => columnType.StartsWith(t, StringComparison.OrdinalIgnoreCase)))
237237
{
238238
// Collation information is not available from the runtime model, so we need to fetch it from the design time model
239-
if (designTimeEntityType == null)
240-
{
241-
var designTimeModel = _ctx.GetService<IDesignTimeModel>().Model;
242-
designTimeEntityType = designTimeModel.FindEntityType(property.Property.DeclaringEntityType.Name) ??
243-
throw new InvalidOperationException($"Entity type {property.Property.DeclaringEntityType.Name} is missing from design time model.");
244-
}
245-
var designTimeEntityProperty = designTimeEntityType.GetProperty(property.Property.Name);
246-
var collation = designTimeEntityProperty.GetCollation(storeObject.Value);
247-
if (string.IsNullOrWhiteSpace(collation) && options.UseDefaultDatabaseCollation)
239+
designTimeEntityType ??= _ctx.GetService<IDesignTimeModel>().Model
240+
.GetEntityType(property.Property.DeclaringEntityType.Name);
241+
242+
var collation = designTimeEntityType.GetProperty(property.Property.Name)
243+
.GetCollation(storeObject.Value);
244+
245+
if (options.UseDefaultDatabaseCollation && String.IsNullOrWhiteSpace(collation))
248246
collation = "database_default";
249-
if (!string.IsNullOrWhiteSpace(collation))
247+
248+
if (!String.IsNullOrWhiteSpace(collation))
250249
sb.Append(" COLLATE ").Append(collation);
251250
}
252251

tests/Thinktecture.EntityFrameworkCore.SqlServer.Tests/EntityFrameworkCore/TempTables/SqlServerTempTableCreatorTests/CreateTempTableAsync.cs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Data.Common;
33
using Microsoft.Data.SqlClient;
44
using Microsoft.EntityFrameworkCore.Infrastructure;
5+
using Microsoft.EntityFrameworkCore.Storage;
56
using Thinktecture.EntityFrameworkCore.BulkOperations;
67
using Thinktecture.TestDatabaseContext;
78

@@ -530,7 +531,7 @@ public async Task Should_create_temp_table_with_decimal()
530531
[Fact]
531532
public async Task Should_create_temp_table_with_decimal_with_explicit_precision()
532533
{
533-
ConfigureModel = builder => builder.ConfigureTempTable<decimal>(typeBuilder => typeBuilder.Property(t => t.Column1).HasPrecision(20,5));
534+
ConfigureModel = builder => builder.ConfigureTempTable<decimal>(typeBuilder => typeBuilder.Property(t => t.Column1).HasPrecision(20, 5));
534535

535536
await using var tempTable = await SUT.CreateTempTableAsync(ActDbContext.GetTempTableEntityType<TempTable<decimal>>(), _optionsWithNonUniqueName);
536537

@@ -700,6 +701,26 @@ public async Task Should_create_temp_table_for_entity_with_many_owned_types()
700701
ValidateColumn(columns[3], nameof(OwnedEntity.StringColumn), "nvarchar", true);
701702
}
702703

704+
[Fact]
705+
public async Task Should_honor_collation()
706+
{
707+
var entityType = ActDbContext.GetTempTableEntityType<TestEntityWithCollation>();
708+
await using var tempTable = await SUT.CreateTempTableAsync(entityType, _optionsWithNonUniqueName);
709+
710+
var columns = AssertDbContext.GetTempTableColumns<TestEntityWithCollation>().ToList();
711+
columns.Should().HaveCount(3);
712+
713+
var connection = AssertDbContext.Database.GetDbConnection();
714+
await using var command = connection.CreateCommand();
715+
command.Transaction = AssertDbContext.Database.CurrentTransaction?.GetDbTransaction();
716+
command.CommandText = "SELECT CONVERT (varchar(256), SERVERPROPERTY('collation'))";
717+
var databaseCollation = (string?)await command.ExecuteScalarAsync() ?? throw new Exception("Couldn't fetch database collection.");
718+
719+
ValidateColumn(columns[0], nameof(TestEntityWithCollation.Id), "uniqueidentifier", false);
720+
ValidateColumn(columns[1], nameof(TestEntityWithCollation.ColumnWithCollation), "nvarchar", false, collation: "Japanese_CI_AS");
721+
ValidateColumn(columns[2], nameof(TestEntityWithCollation.ColumnWithoutCollation), "nvarchar", false, collation: databaseCollation);
722+
}
723+
703724
private static DbConnection CreateConnection()
704725
{
705726
return new SqlConnection(TestContext.Instance.ConnectionString);
@@ -718,7 +739,8 @@ private static void ValidateColumn(
718739
byte? numericPrecision = null,
719740
int? numericScale = null,
720741
int? charMaxLength = null,
721-
string? defaultValue = null)
742+
string? defaultValue = null,
743+
string? collation = null)
722744
{
723745
ArgumentNullException.ThrowIfNull(column);
724746

@@ -727,6 +749,9 @@ private static void ValidateColumn(
727749
column.IS_NULLABLE.Should().Be(isNullable ? "YES" : "NO");
728750
column.COLUMN_DEFAULT.Should().Be(defaultValue);
729751

752+
if (collation is not null)
753+
column.COLLATION_NAME.Should().Be(collation);
754+
730755
if (numericPrecision.HasValue)
731756
column.NUMERIC_PRECISION.Should().Be(numericPrecision.Value);
732757

tests/Thinktecture.EntityFrameworkCore.SqlServer.Tests/TestDatabaseContext/TestDbContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
9999
TestEntity_Owns_SeparateMany_SeparateOne.Configure(modelBuilder);
100100
TestEntity_Owns_SeparateMany_Inline.Configure(modelBuilder);
101101
TestEntity_Owns_SeparateMany_SeparateMany.Configure(modelBuilder);
102+
TestEntityWithCollation.Configure(modelBuilder);
102103

103104
ConfigureModel?.Invoke(modelBuilder);
104105

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace Thinktecture.TestDatabaseContext;
2+
3+
public class TestEntityWithCollation
4+
{
5+
public Guid Id { get; set; }
6+
public string ColumnWithoutCollation { get; set; }
7+
public string ColumnWithCollation { get; set; }
8+
9+
public TestEntityWithCollation(Guid id, string columnWithoutCollation, string columnWithCollation)
10+
{
11+
Id = id;
12+
ColumnWithoutCollation = columnWithoutCollation;
13+
ColumnWithCollation = columnWithCollation;
14+
}
15+
16+
public static void Configure(ModelBuilder modelBuilder)
17+
{
18+
modelBuilder.Entity<TestEntityWithCollation>(builder => builder.Property(e => e.ColumnWithCollation).UseCollation("Japanese_CI_AS"));
19+
}
20+
}

0 commit comments

Comments
 (0)