Skip to content

SqlException fails to deserialize via BinaryFormatter #778

Description

@danlyons-home

Describe the bug

In one project I work on, RPC is done via RabbitMQ, serializing request/reply data with BinaryFormatter. Recently, I ran across an error when deserializing SqlExceptions raised on the back-end.

There appear to be two distinct exceptions raised:

TargetInvokcationException with an inner exception of InvalidCastException when the deserialized exception includes SqlException as its inner exception:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.InvalidCastException: Object must implement IConvertible.
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at System.Runtime.Serialization.FormatterConverter.Convert(Object value, Type type)
   at System.Runtime.Serialization.SerializationInfo.GetValue(String name, Type type)
   at System.Exception..ctor(SerializationInfo info, StreamingContext context)
   at Panther.Common.Database.DBException..ctor(SerializationInfo info, StreamingContext context) in C:\BuildAgent\work\fb44abcc89900f2b\src\server\panther.common.database\DBException.cs:line 136

   --- End of inner exception stack trace ---
   at Panther.Proxy.Common.SyncRequestHelper.SendRequestAsync[T](Object scope, Object payload, TimeSpan timeout, String queueName) in C:\BuildAgent\work\fb44abcc89900f2b\src\server\panther.proxy.common\SyncRequestHelper.cs:line 209
   at Panther.Proxy.Common.SyncRequestHelper.SendRequestAsync[T](String queueName, Object scope, Object payload, TimeSpan timeout) in C:\BuildAgent\work\fb44abcc89900f2b\src\server\panther.proxy.common\SyncRequestHelper.cs:line 116
   at Panther.Common.Extensions.TaskExtensions.SynchronizeResult[T](Task`1 task) in C:\BuildAgent\work\fb44abcc89900f2b\src\server\panther.common\Extensions\TaskExtensions.cs:line 28
   at Panther.Proxy.Common.SyncRequestHelper.SendRequest[T](String queueName, Object scope, Object payload, TimeSpan timeout) in C:\BuildAgent\work\fb44abcc89900f2b\src\server\panther.proxy.common\SyncRequestHelper.cs:line 75
   at Panther.Proxy.Client.BaseFailoverProxy.SendRequest[T](Keys scope, Object payload) in C:\BuildAgent\work\fb44abcc89900f2b\src\server\panther.proxy.client\BaseFailoverProxy.cs:line 28
   at Panther.Proxy.Client.PrivCache.PrivCacheFailoverProxy.SavePrivilegeValues(IEnumerable`1 accountPrivs, String savedBy) in C:\BuildAgent\work\fb44abcc89900f2b\src\server\panther.proxy.client\PrivCache\PrivCacheFailoverProxy.cs:line 352
   at Panther.Api.Controllers.PrivilegeController.SavePrivileges(IEnumerable`1 privileges) in C:\BuildAgent\work\fb44abcc89900f2b\src\web\panther.api.core\Controllers\PrivilegeController.cs:line 270
   at lambda_method(Closure , Object )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

SerializationException when the deserialized exception is SqlException itself:

System.Runtime.Serialization.SerializationException: Unable to load type Microsoft.Data.SqlClient.SqlException required for deserialization.
   at System.Runtime.Serialization.ObjectManager.DoFixups()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(BinaryParser serParser, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, Boolean check)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
   at testdbexception.Program.Main(String[] args) in C:\danl\testdbexception\Program.cs:line 37

To reproduce

Attached is a minimal reproduction of the issue. TestDir has functions to create a test table, insert a value, and drop the test table. Program calls into TestDir with two inserts of the same value to trigger a SqlException for a primary key violation, then serializes and deserializes the exception with BinaryFormatter.

testdbexception.zip

Expected behavior

I would expect the deserialization to complete successfully, particularly given SqlException is marked as serializable, implements ISerializable, and serializes without issue.

Further technical details

Microsoft.Data.SqlClient version: latest (2.0.1)
.NET target: Core 3.1
SQL Server version: SQL Server 2016
Operating system: Windows 10 (dev machine), Server 2016 (production machine)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions