首页 > 解决方案 > EF Core Hierarchy TPH map two entities to one

问题描述

I have a base project, which has some basic entities. Let's use BaseUser as one. In the child project, it references base project and User class inherits from that BaseUser. The only difference is the User class has List<Blogs>, so no additional properties, no change in mapping.

When I query Users, it does not find any because they are created as BaseUser and the query has discriminator value of "User". I don't want to query "BaseUser" because I want the relational property of List<Blogs>.

Is there any way to tell EF to basically treat these classes as one? Is there a better way to handle the split? (obviously base project has no concept of blogs, so cannot move the List to the base)

Some sample classes as requested

/* Base Project (nuget package created) */
public class BaseUser {
    public int UserId { get; set; }
    public int Name { get; set; }
}

public class BaseContext : DbContext {
    public DbSet<BaseUser> BaseUsers {get;set;}
}

public class BaseDataInstaller {
    BaseContext _ctx;
    public BaseDataInstaller( BaseContext ctx ){
        _ctx = ctx;
    }
    public void Install(){
        _ctx.BaseUsers.Add( new BaseUser { Name="Demo User 1" } );
        _ctx.BaseUsers.Add( new BaseUser { Name="Demo User 2" } );
        _ctx.SaveChanges();
    }
}
/* Child Project (consumes nuget package)*/
public class User : BaseUser {
    List<Blogs> Blogs { get; set; }
}

public class ProjectContext : BaseContext {
    public DbSet<User> Users { get; set; }
}

public class SomeService {
    ProjectContext _ctx;
    public BaseDataInstaller(ProjectContext ctx){
        _ctx = ctx;
    }

    //Finds 0 users
    public void PrintUsers(){
        var users = _ctx.Users.ToList();
        users.ForEach( u=> Console.WriteLine(u.Name) );
    }

    //Finds Users
    public void PrintBaseUsers(){
        var users = _ctx.BaseUsers.ToList();
        users.ForEach( u=> Console.WriteLine(u.Name) );
    }
}

Comparing the SQL generated, there is a discriminator added

where Discriminator = 'BaseUser' or where Discriminator = 'User'

There are no properties which are different between the two, just the relationship with the blogs.

So is there a way to either make both have the same Discriminator value or another way to solve this?

UPDATE 1

The discriminator only appears if the DbContext knows about BOTH entities. if it only knows about the one, it is happy to map onto the table. Even if the child inherits from the base, it still doesn't need a discriminator. So I think the challenge is to re-work the base so the context doesn't know about the base. This does feel like a workaround though. Maybe the structure should change:

instead of User : BaseUser use a property

User
 - int ChildUserId {get; set;}
 - BaseUser BaseUser {get; set;}
 - SomeObject SomeNavProperty etc

it will mean a new table for each inherited project, but would allow the project to add it's own specific data too...

标签: entity-frameworkentity-framework-coresingle-table-inheritance

解决方案


推荐阅读