diff --git a/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs b/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs
index b8c70fc1195..69897e0742a 100644
--- a/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs
+++ b/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs
@@ -1356,7 +1356,8 @@ protected virtual void ColumnDefinition(
return;
}
- var columnType = operation.ColumnType ?? GetColumnType(schema, table, name, operation, model)!;
+ var columnType = operation.ColumnType ?? GetColumnType(schema, table, name, operation, model);
+
builder
.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(name))
.Append(" ")
@@ -1401,7 +1402,7 @@ protected virtual void ComputedColumnDefinition(
/// The column metadata.
/// The target model which may be if the operations exist without a model.
/// The database/store type for the column.
- protected virtual string? GetColumnType(
+ protected virtual string GetColumnType(
string? schema,
string tableName,
string name,
@@ -1429,7 +1430,7 @@ protected virtual void ComputedColumnDefinition(
|| table.Indexes.Any(u => u.Columns.Contains(column));
}
- return Dependencies.TypeMappingSource.FindMapping(
+ var storeType = Dependencies.TypeMappingSource.FindMapping(
operation.ClrType,
null,
keyOrIndex,
@@ -1440,6 +1441,15 @@ protected virtual void ComputedColumnDefinition(
operation.Precision,
operation.Scale)
?.StoreType;
+
+ if (storeType != null)
+ {
+ return storeType;
+ }
+
+ var fullTableName = schema != null ? $"{schema}.{tableName}" : tableName;
+ throw new InvalidOperationException(
+ RelationalStrings.UnsupportedTypeForColumn(fullTableName, name, operation.ClrType?.Name ?? "unknown"));
}
///
diff --git a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs
index 1248246cde2..c482e874ef2 100644
--- a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs
+++ b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs
@@ -2241,6 +2241,14 @@ public static string UnsupportedType(object? clrType)
GetString("UnsupportedType", nameof(clrType)),
clrType);
+ ///
+ /// Unable to find a store type mapping for column '{table}.{column}' with CLR type '{clrType}'.
+ ///
+ public static string UnsupportedTypeForColumn(object? table, object? column, object? clrType)
+ => string.Format(
+ GetString("UnsupportedTypeForColumn", nameof(table), nameof(column), nameof(clrType)),
+ table, column, clrType);
+
///
/// The database operation was expected to affect {expectedRows} row(s), but actually affected {actualRows} row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
///
diff --git a/src/EFCore.Relational/Properties/RelationalStrings.resx b/src/EFCore.Relational/Properties/RelationalStrings.resx
index c600ef49f15..6c91cc2ebeb 100644
--- a/src/EFCore.Relational/Properties/RelationalStrings.resx
+++ b/src/EFCore.Relational/Properties/RelationalStrings.resx
@@ -1306,6 +1306,9 @@
The current provider doesn't have a store type mapping for properties of type '{clrType}'.
+
+ Unable to find a store type mapping for column '{table}.{column}' with CLR type '{clrType}'.
+
The database operation was expected to affect {expectedRows} row(s), but actually affected {actualRows} row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
diff --git a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs
index d57bfa6b187..a59c7413f9d 100644
--- a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs
+++ b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs
@@ -383,9 +383,7 @@ protected override void Generate(
{
Check.DebugAssert(operation.DefaultValue is not null);
- var typeMapping = (columnType != null
- ? Dependencies.TypeMappingSource.FindMapping(operation.DefaultValue.GetType(), columnType)
- : null)
+ var typeMapping = Dependencies.TypeMappingSource.FindMapping(operation.DefaultValue.GetType(), columnType)
?? Dependencies.TypeMappingSource.GetMappingForValue(operation.DefaultValue);
defaultValueSql = typeMapping.GenerateSqlLiteral(operation.DefaultValue);
@@ -1640,7 +1638,7 @@ protected override void ColumnDefinition(
return;
}
- var columnType = operation.ColumnType ?? GetColumnType(schema, table, name, operation, model)!;
+ var columnType = operation.ColumnType ?? GetColumnType(schema, table, name, operation, model);
builder
.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(name))
.Append(" ")
diff --git a/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs b/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs
index d1d6e7e23ff..e43c0a88572 100644
--- a/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs
+++ b/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs
@@ -58,7 +58,7 @@ private bool IsSpatialiteColumn(AddColumnOperation operation, IModel? model)
operation.Table,
operation.Name,
operation,
- model)!);
+ model));
private IReadOnlyList RewriteOperations(
IReadOnlyList migrationOperations,
diff --git a/test/EFCore.SqlServer.FunctionalTests/Migrations/SqlServerMigrationsSqlGeneratorTest.cs b/test/EFCore.SqlServer.FunctionalTests/Migrations/SqlServerMigrationsSqlGeneratorTest.cs
index f8d9cb99007..22ddb64c6bf 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Migrations/SqlServerMigrationsSqlGeneratorTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Migrations/SqlServerMigrationsSqlGeneratorTest.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal;
@@ -1267,6 +1268,25 @@ FROM [sys].[default_constraints] [d]
""");
}
+
+
+ [ConditionalFact]
+ public void Invalid_column_type_for_unmappable_clr_type_throws_meaningful_exception()
+ {
+ var ex = Assert.Throws(() =>
+ Generate(
+ new AddColumnOperation
+ {
+ Name = "TestColumn",
+ Table = "TestTable",
+ ClrType = typeof(System.IO.FileStream), // Unmappable CLR type
+ ColumnType = null,
+ IsNullable = false
+ }));
+
+ Assert.Equal(RelationalStrings.UnsupportedTypeForColumn("TestTable", "TestColumn", "FileStream"), ex.Message);
+ }
+
private static void CreateGotModel(ModelBuilder b)
=> b.HasDefaultSchema("dbo").Entity(
"Person", pb =>