EF6 Automapper Inheritance/Abstract Class Errors

Deadly 提交于 2020-07-10 11:33:06

问题


I'm building a .NET Web API using Entity Framework 6 with AutoMapper to map entities to DTOs. When I try to introduce an TPH (table per hierarchy) with an abstract base class, I get a very long and very useless (to me at least) error. The error is below, I'm not sure what the actual error is. I've tried Googling various sections of it to no avail.

This is my mapping:

        Mapper.CreateMap<ParentClass, ParentClassDTO>()
            .Include<ClassA, ClassADTO>()
            .Include<ClassB, ClassBDTO>();

        Mapper.CreateMap<ClassA, ClassADTO>();
        Mapper.CreateMap<ClassB, ClassBDTO>();

If I remove abstract from the ParentClass, the error goes away but then AutoMapper does not use the child DTO classes, it only uses the ParentClassDTO. If I remove the mapping all together and just return the entities through the API, there are no errors and everything works as expected.

I don't even know where to start with the error below, how to start debugging it (web API running in debug mode still just outputs this error to screen), or what is responsible for the error. I've simplified my code as much as possible and tried other various things, but can't seem to get around this issue.

This specific mapping is a collection within another DTO class, which I am creating to return a IQueryable<AnotherClassDTO> from a Web API:

return db.AnotherClass.Project().To<AnotherClassDTO>();

The AnotherClassDTO (a separate class which contains the abstract collection) is setup like this:

public class AnotherClassDTO
{
    public IEnumerable<ParentClassDTO> Elements;
}

Error Message:

> {"message":"An error has occurred.","exceptionMessage":"The
> 'ObjectContent`1' type failed to serialize the response body for
> content type 'text/html;
> charset=utf-8'.","exceptionType":"System.InvalidOperationException","stackTrace":null,"innerException":{"message":"An
> error has occurred.","exceptionMessage":"Exception has been thrown by
> the target of an
> invocation.","exceptionType":"System.Reflection.TargetInvocationException","stackTrace":"
> at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[]
> arguments, Signature sig, Boolean constructor)\r\n at
> System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj,
> Object[] parameters, Object[] arguments)\r\n at
> System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags
> invokeAttr, Binder binder, Object[] parameters, CultureInfo
> culture)\r\n at System.Reflection.MethodBase.Invoke(Object obj,
> Object[] parameters)\r\n at
> System.Data.Entity.Core.Common.Internal.Materialization.Translator.TranslateColumnMap(Translator
> translator, Type elementType, ColumnMap columnMap, MetadataWorkspace
> workspace, SpanIndex spanIndex, MergeOption mergeOption, Boolean
> streaming, Boolean valueLayer)\r\n at
> System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlanFactory.Prepare(ObjectContext
> context, DbQueryCommandTree tree, Type elementType, MergeOption
> mergeOption, Boolean streaming, Span span, IEnumerable`1
> compiledQueryParameters, AliasGenerator aliasGenerator)\r\n at
> System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1
> forMergeOption)\r\n at
> System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.b__6()\r\n
> at
> System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1
> func, IDbExecutionStrategy executionStrategy, Boolean
> startLocalTransaction, Boolean releaseConnectionOnSuccess)\r\n at
> System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.b__5()\r\n
> at
> System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1
> operation)\r\n at
> System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1
> forMergeOption)\r\n at
> System.Data.Entity.Core.Objects.ObjectQuery`1..GetEnumerator>b__0()\r\n
> at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()\r\n at
> Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter
> writer, IEnumerable values, JsonArrayContract contract, JsonProperty
> member, JsonContainerContract collectionContract, JsonProperty
> containerProperty)\r\n at
> Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter
> writer, Object value, JsonContract valueContract, JsonProperty member,
> JsonContainerContract containerContract, JsonProperty
> containerProperty)\r\n at
> Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter
> jsonWriter, Object value, Type objectType)\r\n at
> Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter
> jsonWriter, Object value, Type objectType)\r\n at
> Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object
> value)\r\n at
> System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type
> type, Object value, Stream writeStream, Encoding
> effectiveEncoding)\r\n at
> System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type
> type, Object value, Stream writeStream, Encoding
> effectiveEncoding)\r\n at
> System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type
> type, Object value, Stream writeStream, HttpContent content)\r\n at
> System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type
> type, Object value, Stream writeStream, HttpContent content,
> TransportContext transportContext, CancellationToken
> cancellationToken)\r\n--- End of stack trace from previous location
> where exception was thrown ---\r\n at
> System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
> task)\r\n at
> System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
> task)\r\n at
> System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n at
> System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()","innerException":{"message":"An
> error has occurred.","exceptionMessage":"Exception has been thrown by
> the target of an
> invocation.","exceptionType":"System.Reflection.TargetInvocationException","stackTrace":"
> at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[]
> arguments, Signature sig, Boolean constructor)\r\n at
> System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags
> invokeAttr, Binder binder, Object[] parameters, CultureInfo
> culture)\r\n at System.RuntimeType.CreateInstanceImpl(BindingFlags
> bindingAttr, Binder binder, Object[] args, CultureInfo culture,
> Object[] activationAttributes, StackCrawlMark& stackMark)\r\n at
> System.Activator.CreateInstance(Type type, BindingFlags bindingAttr,
> Binder binder, Object[] args, CultureInfo culture, Object[]
> activationAttributes)\r\n at System.Activator.CreateInstance(Type
> type, Object[] args)\r\n at
> System.Data.Entity.Core.Common.Internal.Materialization.CoordinatorScratchpad.Compile()\r\n
> at
> System.Data.Entity.Core.Common.Internal.Materialization.CoordinatorScratchpad.Compile()\r\n
> at
> System.Data.Entity.Core.Common.Internal.Materialization.CoordinatorScratchpad.Compile()\r\n
> at
> System.Data.Entity.Core.Common.Internal.Materialization.Translator.TranslateColumnMap[T](ColumnMap
> columnMap, MetadataWorkspace workspace, SpanIndex spanIndex,
> MergeOption mergeOption, Boolean streaming, Boolean
> valueLayer)","innerException":{"message":"An error has
> occurred.","exceptionMessage":"Instances of abstract classes cannot be
> created.","exceptionType":"System.InvalidOperationException","stackTrace":"
> at
> System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(IRuntimeMethodInfo
> method)\r\n at
> System.Reflection.Emit.DynamicMethod.CreateDelegate(Type delegateType,
> Object target)\r\n at
> System.Linq.Expressions.Compiler.LambdaCompiler.CreateDelegate()\r\n
> at
> System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression
> lambda, DebugInfoGenerator debugInfoGenerator)\r\n at
> System.Linq.Expressions.Expression`1.Compile()\r\n at
> System.Data.Entity.Core.Common.Internal.Materialization.CoordinatorFactory`1..ctor(Int32
> depth, Int32 stateSlot, Expression`1 hasData, Expression`1 setKeys,
> Expression`1 checkKeys, CoordinatorFactory[] nestedCoordinators,
> Expression`1 element, Expression`1 wrappedElement, Expression`1
> elementWithErrorHandling, Expression`1 initializeCollection,
> RecordStateFactory[] recordStateFactories)\r\n at
> System.Data.Entity.Core.Common.Internal.Materialization.CoordinatorFactory`1..ctor(Int32
> depth, Int32 stateSlot, Expression hasData, Expression setKeys,
> Expression checkKeys, CoordinatorFactory[] nestedCoordinators,
> Expression element, Expression elementWithErrorHandling, Expression
> initializeCollection, RecordStateFactory[] recordStateFactories)"}}}}

回答1:


2 problems

  1. The error message clearly states that you can't map an abstract class
  2. You're working with Queryable extensions Project().To<T>() which seems to suffer, in this case, from limitations due to linq provider, as mentionned here

=> make your base class concrete

=> map from an IEnumerable<T> instead of an IQueryable<T>, without using Queryable extensions.



来源:https://stackoverflow.com/questions/29815761/ef6-automapper-inheritance-abstract-class-errors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!