Reputation: 1050
I am migrating legacy code from .NET Framework 4.52 to netstandard1.4 (FWIW, I am also migrating from EF 6 to EF Core).
MY problem stems from IDbSet<T>
not being currently implemented in EF Core.
In EF 6, IDbSet<Plugin>.Add(entity)
returns a proxy of the Plugin type.
In EF Core, context.Set<Plugin>.Add(entity)
returns {Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry`1[Dna.NetCore.Core.BLL.Entities.Plugins.Plugin]}.
I'm getting the following exceptions when casting from Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry`1[Dna.NetCore.Core.BLL.Entities.Plugins.Plugin] to Dna.NetCore.Core.BLL.Entities.Plugins.Plugin in EF Core.
Q - How can I cast this?
public abstract class RepositoryBase<T, U>
where T : class
where U : DbContext, new()
{
private U _dataContext;
private readonly IDbSet<T> _dbset;
public virtual T Add(T entity)
{
object dao = _dbset.Add(entity);
return dao as T;
}
}
public abstract class RepositoryBase<T>
where T : class
{
//private readonly IDbSet<T> _dbset; // IDbSet is not implemented in .NET Core 1.0.1
private readonly Microsoft.EntityFrameworkCore.DbSet<T> _dbset;
private readonly CoreEFContext _context;
protected RepositoryBase(CoreEFContext context)
{
_context = context;
_dbset = _context.Set<T>();
}
public virtual T Add(T entity, out CustomMessage customMessage)
{
object dao = _dbset.Add(entity);
return dao as T;
}
}
The repository is available in GitHub.
this._dbset.Results View = "Enumeration yielded no results"
this._context.ChangeTracker.Non-Public members.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure.Instance.Entries[0] = does contain the entity
(Dna.NetCore.Core.BLL.Entities.Plugins.Plugin)dao
'(Dna.NetCore.Core.BLL.Entities.Plugins.Plugin)dao' threw an exception of type 'System.InvalidCastException'
Data: {System.Collections.ListDictionaryInternal}
HResult: -2147467262
HelpLink: null
InnerException: null
Message: "Specified cast is not valid."
Source: null
StackTrace: null
dao as T
'dao as T' threw an exception of type 'System.NullReferenceException'
Data: {System.Collections.ListDictionaryInternal}
HResult: -2147467261
HelpLink: null
InnerException: null
Message: "Object reference not set to an instance of an object."
Source: null
StackTrace: null
dao.GetType()
{Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry
1[Dna.NetCore.Core.BLL.Entities.Plugins.Plugin]}
1[[Dna.NetCore.Core.BLL.Entities.Plugins.Plugin, Dna.NetCore.Core.BLL, Version=1.0.1.0, Culture=neutral, PublicKeyToken=null]], Microsoft.EntityFrameworkCore, Version=1.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60"
Assembly: {Microsoft.EntityFrameworkCore, Version=1.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60}
AssemblyQualifiedName: "Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry
Attributes: Public | BeforeFieldInit
BaseType: {Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry}
ContainsGenericParameters: false
CustomAttributes: Count = 0
DeclaredConstructors: {System.Reflection.ConstructorInfo1}
DeclaredEvents: {System.Reflection.EventInfo[0]}
DeclaredFields: {System.Reflection.FieldInfo[0]}
DeclaredMembers: {System.Reflection.MemberInfo[5]}
DeclaredMethods: {System.Reflection.MethodInfo[3]}
DeclaredNestedTypes: {System.Reflection.TypeInfo.d__23}
DeclaredProperties: {System.Reflection.PropertyInfo1}
DeclaringMethod: '((System.RuntimeType)(dao.GetType())).DeclaringMethod' threw an exception of type 'System.InvalidOperationException'
DeclaringType: null
FullName: "Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry1[[Dna.NetCore.Core.BLL.Entities.Plugins.Plugin, Dna.NetCore.Core.BLL, Version=1.0.1.0, Culture=neutral, PublicKeyToken=null]]"
1"
GUID: {bbf992a5-ba4d-3ab3-8a66-fa5a37a909ae}
GenericParameterAttributes: '((System.RuntimeType)(dao.GetType())).GenericParameterAttributes' threw an exception of type 'System.InvalidOperationException'
GenericParameterPosition: '((System.RuntimeType)(dao.GetType())).GenericParameterPosition' threw an exception of type 'System.InvalidOperationException'
GenericTypeArguments: {System.Type[1]}
GenericTypeParameters: {System.Type[0]}
HasElementType: false
ImplementedInterfaces: {System.Type[1]}
IsAbstract: false
IsAnsiClass: true
IsArray: false
IsAutoClass: false
IsAutoLayout: true
IsByRef: false
IsCOMObject: false
IsClass: true
IsConstructedGenericType: true
IsEnum: false
IsExplicitLayout: false
IsGenericParameter: false
IsGenericType: true
IsGenericTypeDefinition: false
IsImport: false
IsInterface: false
IsLayoutSequential: false
IsMarshalByRef: false
IsNested: false
IsNestedAssembly: false
IsNestedFamANDAssem: false
IsNestedFamORAssem: false
IsNestedFamily: false
IsNestedPrivate: false
IsNestedPublic: false
IsNotPublic: false
IsPointer: false
IsPrimitive: false
IsPublic: true
IsSealed: false
IsSecurityCritical: true
IsSecuritySafeCritical: false
IsSecurityTransparent: false
IsSerializable: false
IsSpecialName: false
IsUnicodeClass: false
IsValueType: false
IsVisible: true
MemberType: TypeInfo
MetadataToken: 33554824
Module (System.Reflection.MemberInfo): {Microsoft.EntityFrameworkCore.dll}
Module: {Microsoft.EntityFrameworkCore.dll}
Name: "EntityEntry
Namespace: "Microsoft.EntityFrameworkCore.ChangeTracking"
ReflectedType: null
StructLayoutAttribute: {System.Runtime.InteropServices.StructLayoutAttribute}
TypeHandle: {System.RuntimeTypeHandle}
TypeInitializer: null
UnderlyingSystemType: {Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry`1[Dna.NetCore.Core.BLL.Entities.Plugins.Plugin]}
Dna.NetCore.Core.DAL.EFCore.Repositories.RepositoryBase.Add returned null Dna.NetCore.Core.BLL.Entities.Plugins.Plugin
Upvotes: 2
Views: 896
Reputation: 100741
You should be able to access the entity via the Entity
property on DbSet. You could directly return the parameter or access the EntityEntry<T>
object to give ER Core complete control over what to do:
public virtual T Add(T entity, out CustomMessage customMessage)
{
var entry = _dbset.Add<T>(entity);
...
return entry.Entity;
}
Be aware that currently EF Core does not have EF 6's proxy functionality.
Upvotes: 1