简体   繁体   English

使用自定义ValueConverter时Select上的System.InvalidCastException

[英]System.InvalidCastException on Select when using custom ValueConverter

Problem 问题

I'm trying to introduce a strongly typed ID in one of my entities. 我正在尝试在我的一个实体中引入强类型ID。 To do so, I followed the instructions on https://andrewlock.net/using-strongly-typed-entity-ids-to-avoid-primitive-obsession-part-3/ 为此,我遵循了https://andrewlock.net/using-strongly-typed-entity-ids-to-avoid-primitive-obsession-part-3/上的说明

The only difference to the instructions above is, that I'm trying to persist my ID as a string instead of a Guid. 与上述说明的唯一区别是,我试图将ID保留为字符串而不是Guid。

A short summary of the instructions (a full example can be downloaded here: https://drive.google.com/file/d/1_mtYp1c8W6qJoEAY-8NPNjYvsSAif4mz/view?usp=sharing ): 说明的简短摘要(可在此处下载完整示例: https : //drive.google.com/file/d/1_mtYp1c8W6qJoEAY-8NPNjYvsSAif4mz/view?usp=sharing ):

  • Create a struct "OrderId" with a property "Value", which returns the string representation of the ID 创建具有属性“ Value”的结构“ OrderId”,该结构返回ID的字符串表示形式
  • Create the class for the Order entity and add a property "ID" of type "OrderId" 为Order实体创建类,并添加类型为“ OrderId”的属性“ ID”
  • Create the DbContext with a DbSet 使用DbSet创建DbContext
  • Create a custom ValueConverter that converts OrderId to string and vice versa 创建一个自定义ValueConverter,将OrderId转换为字符串,反之亦然
  • Apply the value converter to the Id column of the Order entity 将值转换器应用于Order实体的Id列
  • Add an explicit conversion operator from OrderId to string to the OrderId in order to avoid client-side evaluations 为了避免客户端评估,将一个从OrderId到字符串的显式转换运算符添加到OrderId中

With this setup, it's no problem to add entries to the Orders table. 使用此设置,将条目添加到“订单”表中没问题。 BUT: when I try to read them, the following exception is thrown: 但是:当我尝试阅读它们时,会引发以下异常:

System.InvalidCastException
  HResult=0x80004002
  Message=Invalid cast from 'System.String' to 'StronglyTypedIds.OrderId'.
  Source=System.Private.CoreLib
  StackTrace:
   at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) in E:\A\_work\644\s\src\mscorlib\shared\System\Convert.cs:line 309
   at Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter`2.Sanitize[T](Object value) in /_/src/EFCore/Storage/ValueConversion/ValueConverter`.cs:line 52
   at Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter`2.<>c__DisplayClass3_0`2.<SanitizeConverter>b__0(Object v) in /_/src/EFCore/Storage/ValueConversion/ValueConverter`.cs:line 43
   at Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping.CreateParameter(DbCommand command, String name, Object value, Nullable`1 nullable) in /_/src/EFCore.Relational/Storage/RelationalTypeMapping.cs:line 515
   at Microsoft.EntityFrameworkCore.Storage.Internal.TypeMappedRelationalParameter.AddDbParameter(DbCommand command, Object value) in /_/src/EFCore.Relational/Storage/Internal/TypeMappedRelationalParameter.cs:line 66
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalParameterBase.AddDbParameter(DbCommand command, IReadOnlyDictionary`2 parameterValues) in /_/src/EFCore.Relational/Storage/Internal/RelationalParameterBase.cs:line 45
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.CreateCommand(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues) in /_/src/EFCore.Relational/Storage/Internal/RelationalCommand.cs:line 375
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues) in /_/src/EFCore.Relational/Storage/Internal/RelationalCommand.cs:line 149
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues) in /_/src/EFCore.Relational/Storage/Internal/RelationalCommand.cs:line 119
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer) in /_/src/EFCore.Relational/Query/Internal/QueryingEnumerable.cs:line 111
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext() in /_/src/EFCore.Relational/Query/Internal/QueryingEnumerable.cs:line 93
   at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found) in E:\A\_work\286\s\corefx\src\System.Linq\src\System\Linq\First.cs:line 63
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ResultEnumerable`1.GetEnumerator() in /_/src/EFCore/Query/Internal/LinqOperatorProvider.cs:line 294
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__17`2.MoveNext() in /_/src/EFCore/Query/Internal/LinqOperatorProvider.cs:line 185
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext() in /_/src/EFCore/Query/Internal/LinqOperatorProvider.cs:line 143
   at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found) in E:\A\_work\286\s\corefx\src\System.Linq\src\System\Linq\First.cs:line 63
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source) in E:\A\_work\286\s\corefx\src\System.Linq\src\System\Linq\First.cs:line 14
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass15_1`1.<CompileQueryCore>b__0(QueryContext qc) in /_/src/EFCore/Query/Internal/QueryCompiler.cs:line 132
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate) in E:\A\_work\286\s\corefx\src\System.Linq.Queryable\src\System\Linq\Queryable.cs:line 741
   at StronglyTypedIds.Program.Main() in <path_to_project>\StronglyTypedIds\StronglyTypedIds\Program.cs:line 29

The weird thing is, that it seems to depend on how I build my Where-query: 奇怪的是,这似乎取决于我如何构建Where-query:

var order = dbContext.Orders.Where(o => (string)o.Id == "1").ToList();                             // works


const string idAsStringConstant = "1";
order = dbContext.Orders.Where(o => (string)o.Id == idAsStringConstant).ToList();                  // works


var idAsStringVariable = "1";
order = dbContext.Orders.Where(o => (string)o.Id == idAsStringVariable).ToList();                  // doesn't work


order = dbContext.Orders.Where(o => (string)o.Id == OrderId.Parse("1").StringValue).ToList();      // doesn't work

Steps to reproduce 重现步骤

Here is a small VS2019 solution with an example: https://drive.google.com/file/d/1_mtYp1c8W6qJoEAY-8NPNjYvsSAif4mz/view?usp=sharing 这是一个带有示例的VS2019小型解决方案: https ://drive.google.com/file/d/1_mtYp1c8W6qJoEAY-8NPNjYvsSAif4mz/view?usp=sharing

Further technical details 更多技术细节

EF Core version: 2.2.6 Database Provider: Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Sqlite Operating system: Windows 10 1809 IDE: (eg Visual Studio 2019 16.1.6) EF Core版本:2.2.6数据库提供程序:Microsoft.EntityFrameworkCore.SqlServer和Microsoft.EntityFrameworkCore.Sqlite操作系统:Windows 10 1809 IDE:(例如Visual Studio 2019 16.1.6)

Ok, it's a bug in Entity Framework. 好的,这是实体框架中的错误。 If I install the preview of version 3.0 of .NET Core and Entity Framework Core it works as expected. 如果我安装了.NET Core和Entity Framework Core 3.0版的预览版,则它将按预期工作。 Further there seems to be a fix for version 2.2 which just wasn't released yet (see https://github.com/aspnet/EntityFrameworkCore/issues/17610 ). 此外,似乎还有一个针对2.2版的修复程序,该修复程序尚未发布(请参阅https://github.com/aspnet/EntityFrameworkCore/issues/17610 )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用COM接口时System.InvalidCastException - System.InvalidCastException when using a COM interface 使用datagridview时发生System.InvalidCastException - System.InvalidCastException when work with datagridview System.InvalidCastException在 - System.InvalidCastException in foreach 中的 System.InvalidCastException - System.InvalidCastException in foreach 服务器上的System.InvalidCastException - System.InvalidCastException On Server SQL 服务器 (ORM) select 来自数据库的数据 - System.InvalidCastException - SQL Server (ORM) select data from database - System.InvalidCastException System.InvalidCastException &quot;对象必须实现 IConvertible。&quot; 使用 BinaryFormatter 反序列化字典时 - System.InvalidCastException "Object must implement IConvertible." when deserializing a Dictionary using a BinaryFormatter C#System.InvalidCastException:&#39;指定的转换无效。&#39; 将MySQL与Discord.Net一起使用时 - C# System.InvalidCastException: 'Specified cast is not valid.' When using MySQL with Discord.Net 将对象类型强制转换为自定义类时发生System.InvalidCastException - System.InvalidCastException while casting an object type to custom class System.InvalidCastException:尝试在 C# 中使用实体框架将对象添加到 SQL 数据库时 - System.InvalidCastException: When trying to add an object to a SQL database using Entity Framework in C#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM