Reputation: 598
What i want is to have a base class and two separate lists of inherited classes. This is my model:
public class Instance
{
public int InstanceId { get; set; }
public virtual ICollection<User> Users { get; internal set; }
public virtual ICollection<MasterUser> MasterUsers { get; internal set; }
}
public abstract class CoreUser
{
[Key]
public int UserId { get; set; }
public int InstanceId { get; set; }
public virtual Instance Instance { get; set; }
}
[Table("Users")]
public class User : CoreUser
{
public string UserName { get; set; }
}
[Table("MasterUsers")]
public class MasterUser : CoreUser
{
public string MasterUserName { get; set; }
}
This is my DbContext:
public class MyContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<MasterUser> MasterUsers { get; set; }
public DbSet<Instance> Instances { get; set; }
}
This will create 4 tables with TPT inheritance model which is fine. The problem is Users and MasterUsers table will contain foreign key to Instance (it will be called Instance_InstanceId) which is redundant since this FK is defined in the CoreUser base class. These two FK columns are not even populated, they are always NULL, CoreUsers InstanceId column is populated when you add either User or MasterUser.
If I remove both referenced from Instance class like so:
public class Instance
{
public int InstanceId { get; set; }
}
Problem goes away but that also renders my application unusable. I can also solve my problem like so:
public class Instance
{
public int InstanceId { get; set; }
public virtual ICollection<CoreUser> Users { get; internal set; }
}
And then iterate trough collection filtering out each type of user but this approach will lazy load all of the users even though I just want to iterate trough MasterUsers only.
One possible solution was to use TPC but in reality, CoreUser class will contain FKs to some other Classes which is not supported in TPC (only top level classes in hierarchy can contain FKs). Is there any way I can get this to work in EF using two separate lists in Instance class and have them lazy loaded?
EDIT
Actually, the above code would work just fine. It will break if you introduce one more class that references CoreUser for example:
public class UserPolicy
{
public int PolicyId { get; set; }
public virtual CoreUser PolicyUser { get; internal set; }
}
Upvotes: 3
Views: 235
Reputation: 598
Managed to get around this. Solution that I was able to use is to move relationship between CoreUser and Instance to User and MasterUser like so:
public class Instance
{
public int InstanceId { get; set; }
// Still referencing two lists
public virtual ICollection<User> Users { get; internal set; }
public virtual ICollection<MasterUser> MasterUsers { get; internal set; }
}
public abstract class CoreUser
{
[Key]
public int UserId { get; set; }
// No reference to instance. Works if you don't need it from CoreUser
}
[Table("Users")]
public class User : CoreUser
{
// FK to Instance defined in CoreUser
public int InstanceId { get; set; }
public virtual Instance Instance { get; set; }
public string UserName { get; set; }
}
[Table("MasterUsers")]
public class MasterUser : CoreUser
{
// FK to Instance defined in MasterUser
public int InstanceId { get; set; }
public virtual Instance Instance { get; set; }
public string MasterUserName { get; set; }
}
Upvotes: 1