Open mindlink opened 4 years ago
This is the SQL generated by migrations:
INSERT INTO [Messages] ([MessageId], [GroupId], [SenderId], [Content], [Timestamp], [Context])
VALUES (N'dde5f8b1-980c-45c1-9921-ff087bf4e52e', N'390fca16-47bb-46f8-9719-e42e843c7f11', N'3aad58d1-5cfb-4007-99af-8edae40e1e0a', N'This is content inserted as part of a migration', '2020-08-27T00:25:37.0870009+00:00', N'Some context');
It also throws the same exception when executed from SSMS because the values are hardcoded instead of being supplied in parameters.
When the migration is executed (as opposed to generating a script) parameters should be used instead of hardcoding the values.
@mindlink This is currently a limitation in how migrations were designed. We recommend populating tables with encrypted columns using SaveChanges
. This way you can also avoid having the unencrypted data in the source code.
When inserting data during a migration (using the migration builder API) into a table that has an SQL Always Encrypted column, the operation throws an
SqlException
(see below).When using a
DbContext
to insert data after the migration it works as expected, but the migration API doesn't seem to follow the same mechanism and fails.Steps to reproduce
See https://github.com/mindlink/bug-efcore-encrypted-migration for a minimal sample project that demonstrates this.
Stack trace:
Microsoft.Data.SqlClient.SqlException HResult=0x80131904 Message=Operand type clash: nvarchar is incompatible with nvarchar(4000) encrypted with (encryption_type = 'RANDOMIZED', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'CEK_Auto1', column_encryption_key_database_name = 'EFCoreEncryption') Source=Core Microsoft SqlClient Data Provider StackTrace: at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Actiond13.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.d 13.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.d13.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.d 1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.d1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.d 1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.d1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.d 14.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at EncryptionMigrationBug.Program.d3.MoveNext() in C:\Users\terryl\Luke\src\github\bug-efcore-encrypted-migration\EncryptionMigrationBug\Program.cs:line 117
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at EncryptionMigrationBug.Program.d 3.MoveNext() in C:\Users\terryl\Luke\src\github\bug-efcore-encrypted-migration\EncryptionMigrationBug\Program.cs:line 117
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at EncryptionMigrationBug.Program.d0.MoveNext() in C:\Users\terryl\Luke\src\github\bug-efcore-encrypted-migration\EncryptionMigrationBug\Program.cs:line 50
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at EncryptionMigrationBug.Program.d 0.MoveNext() in C:\Users\terryl\Luke\src\github\bug-efcore-encrypted-migration\EncryptionMigrationBug\Program.cs:line 41
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at EncryptionMigrationBug.Program.(String[] args)
1 wrapCloseInAction) at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 wrapCloseInAction) at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at Microsoft.Data.SqlClient.SqlCommand.InternalEndExecuteNonQuery(IAsyncResult asyncResult, Boolean isInternal, String endMethod) at Microsoft.Data.SqlClient.SqlCommand.EndExecuteNonQueryInternal(IAsyncResult asyncResult) at Microsoft.Data.SqlClient.SqlCommand.EndExecuteNonQueryAsync(IAsyncResult asyncResult) at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func
2 endFunction, Action1 endAction, Task
1 promise, Boolean requiresSynchronization) at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.This exception was originally thrown at this call stack: Microsoft.Data.SqlClient.SqlConnection.OnError(Microsoft.Data.SqlClient.SqlException, bool, System.Action)
Microsoft.Data.SqlClient.SqlInternalConnection.OnError(Microsoft.Data.SqlClient.SqlException, bool, System.Action)
Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(Microsoft.Data.SqlClient.TdsParserStateObject, bool, bool)
Microsoft.Data.SqlClient.TdsParser.TryRun(Microsoft.Data.SqlClient.RunBehavior, Microsoft.Data.SqlClient.SqlCommand, Microsoft.Data.SqlClient.SqlDataReader, Microsoft.Data.SqlClient.BulkCopySimpleResultSet, Microsoft.Data.SqlClient.TdsParserStateObject, out bool)
Microsoft.Data.SqlClient.SqlCommand.InternalEndExecuteNonQuery(System.IAsyncResult, bool, string)
Microsoft.Data.SqlClient.SqlCommand.EndExecuteNonQueryInternal(System.IAsyncResult)
Microsoft.Data.SqlClient.SqlCommand.EndExecuteNonQueryAsync(System.IAsyncResult)
System.Threading.Tasks.TaskFactory.FromAsyncCoreLogic(System.IAsyncResult, System.Func<System.IAsyncResult, TResult>, System.Action, System.Threading.Tasks.Task, bool)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
...
[Call Stack Truncated]
Further technical details
EF Core version: 3.1.3 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: NET Core 3.1 Operating system: Windows 10 Enterprise IDE: Visual Studio 2019 16.3