Skip to content

Commit

Permalink
Added test for collection handling in temp table creator.
Browse files Browse the repository at this point in the history
  • Loading branch information
PawelGerr committed Apr 27, 2022
1 parent d8aab67 commit fd69bdc
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -236,17 +236,16 @@ private string GetColumnsDefinitions(SqlServerTempTableCreatorCacheKey options)
if (_stringColumnTypes.Any(t => columnType.StartsWith(t, StringComparison.OrdinalIgnoreCase)))
{
// Collation information is not available from the runtime model, so we need to fetch it from the design time model
if (designTimeEntityType == null)
{
var designTimeModel = _ctx.GetService<IDesignTimeModel>().Model;
designTimeEntityType = designTimeModel.FindEntityType(property.Property.DeclaringEntityType.Name) ??
throw new InvalidOperationException($"Entity type {property.Property.DeclaringEntityType.Name} is missing from design time model.");
}
var designTimeEntityProperty = designTimeEntityType.GetProperty(property.Property.Name);
var collation = designTimeEntityProperty.GetCollation(storeObject.Value);
if (string.IsNullOrWhiteSpace(collation) && options.UseDefaultDatabaseCollation)
designTimeEntityType ??= _ctx.GetService<IDesignTimeModel>().Model
.GetEntityType(property.Property.DeclaringEntityType.Name);

var collation = designTimeEntityType.GetProperty(property.Property.Name)
.GetCollation(storeObject.Value);

if (options.UseDefaultDatabaseCollation && String.IsNullOrWhiteSpace(collation))
collation = "database_default";
if (!string.IsNullOrWhiteSpace(collation))

if (!String.IsNullOrWhiteSpace(collation))
sb.Append(" COLLATE ").Append(collation);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Data.Common;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Thinktecture.EntityFrameworkCore.BulkOperations;
using Thinktecture.TestDatabaseContext;

Expand Down Expand Up @@ -530,7 +531,7 @@ public async Task Should_create_temp_table_with_decimal()
[Fact]
public async Task Should_create_temp_table_with_decimal_with_explicit_precision()
{
ConfigureModel = builder => builder.ConfigureTempTable<decimal>(typeBuilder => typeBuilder.Property(t => t.Column1).HasPrecision(20,5));
ConfigureModel = builder => builder.ConfigureTempTable<decimal>(typeBuilder => typeBuilder.Property(t => t.Column1).HasPrecision(20, 5));

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

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

[Fact]
public async Task Should_honor_collation()
{
var entityType = ActDbContext.GetTempTableEntityType<TestEntityWithCollation>();
await using var tempTable = await SUT.CreateTempTableAsync(entityType, _optionsWithNonUniqueName);

var columns = AssertDbContext.GetTempTableColumns<TestEntityWithCollation>().ToList();
columns.Should().HaveCount(3);

var connection = AssertDbContext.Database.GetDbConnection();
await using var command = connection.CreateCommand();
command.Transaction = AssertDbContext.Database.CurrentTransaction?.GetDbTransaction();
command.CommandText = "SELECT CONVERT (varchar(256), SERVERPROPERTY('collation'))";
var databaseCollation = (string?)await command.ExecuteScalarAsync() ?? throw new Exception("Couldn't fetch database collection.");

ValidateColumn(columns[0], nameof(TestEntityWithCollation.Id), "uniqueidentifier", false);
ValidateColumn(columns[1], nameof(TestEntityWithCollation.ColumnWithCollation), "nvarchar", false, collation: "Japanese_CI_AS");
ValidateColumn(columns[2], nameof(TestEntityWithCollation.ColumnWithoutCollation), "nvarchar", false, collation: databaseCollation);
}

private static DbConnection CreateConnection()
{
return new SqlConnection(TestContext.Instance.ConnectionString);
Expand All @@ -718,7 +739,8 @@ private static void ValidateColumn(
byte? numericPrecision = null,
int? numericScale = null,
int? charMaxLength = null,
string? defaultValue = null)
string? defaultValue = null,
string? collation = null)
{
ArgumentNullException.ThrowIfNull(column);

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

if (collation is not null)
column.COLLATION_NAME.Should().Be(collation);

if (numericPrecision.HasValue)
column.NUMERIC_PRECISION.Should().Be(numericPrecision.Value);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
TestEntity_Owns_SeparateMany_SeparateOne.Configure(modelBuilder);
TestEntity_Owns_SeparateMany_Inline.Configure(modelBuilder);
TestEntity_Owns_SeparateMany_SeparateMany.Configure(modelBuilder);
TestEntityWithCollation.Configure(modelBuilder);

ConfigureModel?.Invoke(modelBuilder);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Thinktecture.TestDatabaseContext;

public class TestEntityWithCollation
{
public Guid Id { get; set; }
public string ColumnWithoutCollation { get; set; }
public string ColumnWithCollation { get; set; }

public TestEntityWithCollation(Guid id, string columnWithoutCollation, string columnWithCollation)
{
Id = id;
ColumnWithoutCollation = columnWithoutCollation;
ColumnWithCollation = columnWithCollation;
}

public static void Configure(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TestEntityWithCollation>(builder => builder.Property(e => e.ColumnWithCollation).UseCollation("Japanese_CI_AS"));
}
}

0 comments on commit fd69bdc

Please sign in to comment.