Source code for this problem is on GitHub
I have the following dbContext for a legacy data structure.
[TypesInfoInitializer(typeof(OrgsContextInitializer))]
public class OrgsEFCoreDbContext : DbContext
{
public OrgsEFCoreDbContext(DbContextOptions<OrgsEFCoreDbContext> options) : base(options)
{
}
public DbSet<ModuleInfo> ModulesInfo { get; set; }
public DbSet<ModelDifference> ModelDifferences { get; set; }
public DbSet<ModelDifferenceAspect> ModelDifferenceAspects { get; set; }
public DbSet<PermissionPolicyRole> Roles { get; set; }
public DbSet<ApplicationUser> Users { get; set; }
public DbSet<ApplicationUserLoginInfo> UserLoginInfos { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Supplier> Suppliers { get; set; }
public DbSet<CustomerContact> CustomerContacts { get; set; }
public DbSet<SupplierContact> SupplierContacts { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ApplicationUserLoginInfo>(b =>
{
b.HasIndex(nameof(DevExpress.ExpressApp.Security.ISecurityUserLoginInfo.LoginProviderName), nameof(DevExpress.ExpressApp.Security.ISecurityUserLoginInfo.ProviderUserKey)).IsUnique();
});
modelBuilder.Entity<Organization>().ToTable("Organizations");
modelBuilder.Entity<Organization>().HasDiscriminator(x => x.OrganizationType)
.HasValue<Customer>(1)
.HasValue<Supplier>(2)
;
modelBuilder.Entity<Contact>().ToTable("Contacts");
modelBuilder.Entity<Contact>().HasDiscriminator(x => x.ContactType)
.HasValue<CustomerContact>(1)
.HasValue<SupplierContact>(2)
;
}
}
When I add a CustomerContact to a Customer I get an error
Unable to cast object of type 'Orgs.Module.BusinessObjects.CustomerContact' to type 'Orgs.Module.BusinessObjects.SupplierContact'.
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.get_Item(IPropertyBase propertyBase)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.GetCurrentValue(IPropertyBase propertyBase)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.TryAddPropertyNameToCollection(InternalEntityEntry entity, ICollection`1 propertiesToCheck, IPropertyBase property)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.TryAddPropertyNameToCollection(InternalEntityEntry entity, IProperty property, ICollection`1 propertiesToCheck)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.GetPropertiesToCheck(InternalEntityEntry entity)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.CheckReadWritePermissionsForNonIntermediateObject(InternalEntityEntry entity)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.CheckReadWritePermissions(InternalEntityEntry entity)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.CheckIsGrantedToSave(InternalEntityEntry entity)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.GetEntriesToSave(Boolean cascadeChanges)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(DbContext _, Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at DevExpress.ExpressApp.EFCore.EFCoreObjectSpace.DoCommit()
at DevExpress.EntityFrameworkCore.Security.SecuredEFCoreObjectSpace.DoCommit()
at DevExpress.ExpressApp.BaseObjectSpace.CommitChanges()
at DevExpress.ExpressApp.Win.SystemModule.WinModificationsController.Save(SimpleActionExecuteEventArgs args)
at DevExpress.ExpressApp.SystemModule.ModificationsController.saveAction_OnExecute(Object sender, SimpleActionExecuteEventArgs e)
at DevExpress.ExpressApp.Actions.SimpleAction.RaiseExecute(ActionBaseEventArgs eventArgs)
at DevExpress.ExpressApp.Actions.ActionBase.ExecuteCore(Delegate handler, ActionBaseEventArgs eventArgs)
The error is the other way around if I try to add a supplier contact to a supplier.
The business classes are as follows;
[NavigationItem("Data")]
public class Customer : Organization
{
public Customer()
{
Contacts = new List<CustomerContact>();
}
public virtual List<CustomerContact> Contacts { get; set; }
}
public class CustomerContact : Contact
{
public CustomerContact() {}
[ForeignKey("OrganizationId")]
public virtual Customer Customer { get; set; }
}
public abstract class Organization
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public string Comments { get; set; }
public int OrganizationType { get; set; }
}
public abstract class Contact
{
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int ContactType { get; set; }
public int OrganizationId { get; set; }
}
At run time the user experience is
Looking at the instructions here I am unsure if this is a Dev Express issue or an Entity Framework issue.