我有一个实体,它有一个字典字段,它使用这样的支持字段。
private Dictionary<string, string> _communicationEventProperties = new Dictionary<string, string>();
public IReadOnlyDictionary<string, string> CommunicationEventProperties => new ReadOnlyDictionary<string,string>(_communicationEventProperties);我已经使用Fluent正确地将它映射到SQL中的JSON。
然而,当我试图调用我的实体时,我会得到以下错误。
System.InvalidCastException: Unable to cast object of type 'System.Collections.ObjectModel.ReadOnlyDictionary`2[System.String,System.String]' to type 'System.Collections.Generic.Dictionary`2[System.String,System.String]'它似乎没有很好地在类型之间映射。
我不知道为什么没有映射/如何使它正确地映射。
我还将附加整个堆栈跟踪:
[InvalidCastException: Unable to cast object of type 'System.Collections.ObjectModel.ReadOnlyDictionary`2[System.String,System.String]' to type 'System.Collections.Generic.Dictionary`2[System.String,System.String]'.]
lambda_method(Closure , MaterializationContext ) +1237
Microsoft.EntityFrameworkCore.Query.EntityLoadInfo.Materialize() +22
Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.GetEntity(IKey key, EntityLoadInfo entityLoadInfo, Boolean queryStateManager, Boolean throwOnNullKey) +201
Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.BufferedEntityShaper`1.Shape(QueryContext queryContext, ValueBuffer& valueBuffer) +198
Microsoft.EntityFrameworkCore.Query.Internal.<BufferlessMoveNext>d__12.MoveNext() +1121
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.<ExecuteAsync>d__7`2.MoveNext() +174
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
Microsoft.EntityFrameworkCore.Query.Internal.<MoveNext>d__11.MoveNext() +637
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
Microsoft.EntityFrameworkCore.Query.Internal.<MoveNext>d__3.MoveNext() +210
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
System.Linq.<FirstOrDefault_>d__165`1.MoveNext() in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\First.cs:144
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
Microsoft.EntityFrameworkCore.Query.Internal.<MoveNext>d__3.MoveNext() +243
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
System.Linq.<MoveNextCore>d__7.MoveNext() in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Select.cs:106
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
System.Linq.<MoveNext>d__10.MoveNext() in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\AsyncIterator.cs:109
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
Microsoft.EntityFrameworkCore.Query.Internal.<MoveNext>d__5.MoveNext() +634
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
Microsoft.EntityFrameworkCore.Query.Internal.<ExecuteSingletonAsyncQuery>d__21`1.MoveNext() +447
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +29
Metis.Communications.Core.EFCore.Interactions.EmailCommunications.GetEmailCommunicationDetails.<<-ctor>g__EmailCommunicationExists|1>d.MoveNext() in C:\Users\ethalacker\source\repos\Metis\src\Communication\Metis.Communications.Core.EFCore\Interactions\EmailCommunications\GetEmailCommunicationDetails\GetEmailCommunicationDetailsValidator.cs:25
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
FluentValidation.Validators.<ValidateAsync>d__7.MoveNext() in /home/jskinner/code/FluentValidation/src/FluentValidation/Validators/PropertyValidator.cs:65
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) +26
FluentValidation.Internal.<ValidateAsync>d__66.MoveNext() in /home/jskinner/code/FluentValidation/src/FluentValidation/Internal/PropertyRule.cs:396
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
FluentValidation.<ValidateAsync>d__14.MoveNext() in /home/jskinner/code/FluentValidation/src/FluentValidation/AbstractValidator.cs:146
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
System.Runtime.CompilerServices.ConfiguredTaskAwaiter.GetResult() +29
Metis.SharedKernel.Interactions.<IsValid>d__10.MoveNext() in C:\Users\ethalacker\source\repos\Metis\src\Shared\Metis.SharedKernel\Interactions\InteractionHandler.cs:77
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +29
Metis.SharedKernel.Interactions.<Handle>d__8.MoveNext() in C:\Users\ethalacker\source\repos\Metis\src\Shared\Metis.SharedKernel\Interactions\InteractionHandler.cs:41
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
MediatR.Pipeline.<Handle>d__2.MoveNext() +260
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
MediatR.Pipeline.<Handle>d__2.MoveNext() +733
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +29
Metis.Web.Pages.SiteConfiguration.Communications.EmailCommunications.EmailCommunicationDetails.<Page>d__3.MoveNext() in C:\Users\ethalacker\source\repos\Metis\src\Metis.Web\Pages\SiteConfiguration\Communications\EmailCommunications\EmailCommunicationDetails\EmailCommunicationDetailsController.cs:38
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +102
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +64
System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +97
System.Web.Mvc.Async.<>c__DisplayClass8_0.<BeginInvokeAsynchronousActionMethod>b__1(IAsyncResult asyncResult) +17
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
System.Web.Mvc.Async.<>c__DisplayClass11_0.<InvokeActionMethodFilterAsynchronouslyRecursive>b__0() +58
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass7_0.<BeginInvokeActionMethodWithFilters>b__1(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
System.Web.Mvc.Async.<>c__DisplayClass3_6.<BeginInvokeAction>b__4() +35
System.Web.Mvc.Async.<>c__DisplayClass3_1.<BeginInvokeAction>b__1(IAsyncResult asyncResult) +100
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
System.Web.Mvc.<>c.<BeginExecuteCore>b__152_1(IAsyncResult asyncResult, ExecuteCoreState innerState) +11
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +45
System.Web.Mvc.<>c.<BeginExecute>b__151_2(IAsyncResult asyncResult, Controller controller) +13
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
System.Web.Mvc.<>c.<BeginProcessRequest>b__20_1(IAsyncResult asyncResult, ProcessRequestState innerState) +28
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.<>c__DisplayClass7_0.<InvokeEndHandler>b__0() +30
System.Web.StepInvoker.Invoke(Action executionStep) +100
System.Web.<>c__DisplayClass4_0.<Invoke>b__0() +17
Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule.OnExecuteRequestStep(HttpContextBase context, Action step) +64
System.Web.<>c__DisplayClass284_0.<OnExecuteRequestStep>b__0(Action nextStepAction) +54
System.Web.StepInvoker.Invoke(Action executionStep) +84
System.Web.CallHandlerExecutionStep.InvokeEndHandler(IAsyncResult ar) +113
System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +126发布于 2020-08-25 19:57:21
我不得不创建一个特殊的json转换器和比较器。在执行IReadOnlyDictionary时,同样可以应用于IReadOnlyList。类将接受属性的类型,然后尝试将其反序列化为字段类型。我有IReadOnlyDictionary和IReadOnlyList的硬编码特例。但是它也可以通过重载(HasJsonConversionWithSerializationType)接受类型。
我还为其他用例添加了一些其他示例。
我的类属性
private Dictionary<string, string> _communicationEventProperties = new Dictionary<string, string>();
public IReadOnlyDictionary<string, string> CommunicationEventProperties => new ReadOnlyDictionary<string,string>(_communicationEventProperties);
private List<TokenValue> _tokenValues = new List<TokenValue>();
public IReadOnlyList<TokenValue> TokenValues => _tokenValues.AsReadOnly();
private List<string> _cCAddresses = new List<string>();
public IReadOnlyList<string> CCAddresses => _cCAddresses.AsReadOnly();
public class TokenValue
{
public string Key { get; }
public string Value { get; }
public TokenValue(string key, string value)
{
// using Dawn. Else you can use a normal "?? throw new ArgumentNullException"
Key = Guard.Argument(key, nameof(Key)).NotNull().NotEmpty().MaxLength(250);
Value = value;
}
}配置文件
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Application.EFCore.Configurations
{
public class MyEntityConfiguration : IEntityTypeConfiguration<MyEntity>
{
public void Configure(EntityTypeBuilder<MyEntity> builder)
{
...
builder.Property(b => b.CommunicationEventProperties)
.HasJsonConversion();
builder.Property(b => b.TokenValues)
.HasJsonConversion();
builder.Property(b => b.CCAddresses)
.HasJsonConversion();
...
}
}
}Json转换类
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public static class BuilderExtensions
{
public static PropertyBuilder<TProperty> HasJsonConversion<TProperty>(this PropertyBuilder<TProperty> propertyBuilder) where TProperty : class
{
var serializationType = GetSerializationTypeByConvention<TProperty>();
return HasJsonConversionWithSerializationType(propertyBuilder, serializationType);
}
public static PropertyBuilder<TProperty> HasJsonConversionWithSerializationType<TProperty, TSerialization>(this PropertyBuilder<TProperty> propertyBuilder)
where TProperty : class
where TSerialization : TProperty
=> HasJsonConversionWithSerializationType(propertyBuilder, typeof(TSerialization));
public static PropertyBuilder<TProperty> HasJsonConversionWithSerializationType<TProperty>(this PropertyBuilder<TProperty> propertyBuilder, Type serializationType) where TProperty : class
{
Guard.Argument(serializationType, nameof(serializationType)).NotNull().Require(t => typeof(TProperty).IsAssignableFrom(t), t => $"Must be able to assign {nameof(serializationType)} '{t.FullName}' to <{nameof(TProperty)}> '{typeof(TProperty).FullName}'");
var converter = MakeConverter<TProperty>(serializationType);
var comparer = MakeComparer<TProperty>(serializationType);
propertyBuilder.HasConversion(converter);
propertyBuilder.Metadata.SetValueConverter(converter);
propertyBuilder.Metadata.SetValueComparer(comparer);
return propertyBuilder;
}
private static Type GetSerializationTypeByConvention<TProperty>() where TProperty : class
{
var typeIsReadOnlyDictionary = typeof(TProperty).IsGenericType && typeof(TProperty).GetGenericTypeDefinition() == typeof(IReadOnlyDictionary<,>);
if (typeIsReadOnlyDictionary) return typeof(Dictionary<,>).MakeGenericType(typeof(TProperty).GetGenericArguments());
var typeIsReadOnlyList = typeof(TProperty).IsGenericType && typeof(TProperty).GetGenericTypeDefinition() == typeof(IReadOnlyList<>);
if (typeIsReadOnlyList) return typeof(List<>).MakeGenericType(typeof(TProperty).GetGenericArguments());
return typeof(TProperty);
}
private static Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer<TProperty> MakeComparer<TProperty>(Type serializationType)
=> new Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer<TProperty>(
(l, r) => Serialize(l) == Serialize(r),
v => v == null ? 0 : Serialize(v).GetHashCode(),
v => Deserialize<TProperty>(Serialize(v), serializationType));
private static ValueConverter<TProperty, string> MakeConverter<TProperty>(Type serializationType)
=> new ValueConverter<TProperty, string>(
v => Serialize(v),
v => Deserialize<TProperty>(v, serializationType));
private static TProperty Deserialize<TProperty>(string v, Type serializationType)
{
if (v == null) return default;
return (TProperty)JsonConvert.DeserializeObject(v, serializationType);
}
private static string Serialize<TProperty>(TProperty v)
=> JsonConvert.SerializeObject(v
, Formatting.None
, new JsonSerializerSettings {
NullValueHandling = NullValueHandling.Ignore
});
}https://stackoverflow.com/questions/63572044
复制相似问题