简体   繁体   中英

Table per Type in Entity Framework Core 2.0

These are my models:

public class Company
{
   public int CompanyId { get; set; }
   public string Name { get; set; }
   public string Address { get; set; }
   public string Email { get; set; }
   public string Url { get; set; }
   //...
}

public class HeadOffice : Company
{
   public int HeadOfficeId { get; set; }
   public virtual List<BranchOffice> BranchOffice { get; set; } = new List<BranchOffice>();
}

public class BranchOffice : Company
{
   public int BranchOfficeId { get; set; }
   public virtual HeadOffice HeadOffice { get; set; }
}

I wanted the following database structure:

Table Company

  • CompanyId (PK)
  • Name
  • Address
  • Email
  • Url

Table HeadOffice

  • HeadOfficeId (PK)
  • CompanyId (FK)

Table BranchOffice

  • BranchOfficeId (PK)
  • HeadOfficeId (FK)
  • CompanyId (FK)

How can I do this?

When I create this migration, the EF creates just one table, with all columns! I don't want this approach!

You would have to change your Model to look like this, note that you can't use inheritance using this approach:

public class Company
{
   public int CompanyId { get; set; }
   //...
}

public class Company
{
   public int CompanyId { get; set; }
   public string Name { get; set; }
   //...
}

public class HeadOffice
{
   [ForeignKey(nameof(Company))]
   public int CompanyId { get; set; }
   public Company Company { get; set; }
   // Add Properties here
}

public class BranchOffice
{
   [ForeignKey(nameof(Company))]
   public int CompanyId { get; set; }
   public Company Company { get; set; }
   // Add Properties here
}

Your DbContext :

public class YourContext : DbContext
{
  public DbSet<Company> Companys { get; set; }
  public DbSet<HeadOffice> HeadOffices { get; set; }
  public DbSet<BranchOffice> BranchOffices { get; set; }

  public YourContext(DbContextOptions<YourContext> options)
    : base(options)
  {
  }
}

You could then use EF Core Migrations . The command would look somewhat like this:

dotnet ef migrations add Initial_TPT_Migration -p ./../../ModelProject.csproj -s ./../../ModelProject.csproj -c YourContext -o ./TptModel/CodeFirst/Migrations

It generats a Class Initial_TPT_Migration that contains methods to generate your database.

Usage

To query you would need to map Company Properties to the fieldnames. If you combine this with the Repository Pattern ( link ), it could actually be as convenient as the default approach in EF Core currently is to use.

YourContext ctx = ...

// Fetch all BranchOffices
var branchOffices = ctx.BranchOffices
          .Select(c => new BranchOffice()
                  {
                    CompanyId = c.CompanyId,
                    Name = c.Company.Name,
                  })
          .ToList();

You can find more informations about this approach here .

You can find an answer here https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/inheritance?view=aspnetcore-2.1

Also check this topic out if you need many inherited classes against one table https://docs.microsoft.com/en-us/ef/core/modeling/relational/inheritance

Copying the code here just in case microsoft used to mess with urls and docs

  1. Each inherited type per table
public class SchoolContext : DbContext
{
    public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
    {
    }

    public DbSet<Student> Students { get; set; }
    public DbSet<Instructor> Instructors { get; set; }
    public DbSet<Person> People { get; set; }

    protected override void OnModelCreating(ModelBuilder b)
    {
        b.Entity<Student>().ToTable("Student");
        b.Entity<Instructor>().ToTable("Instructor");
        b.Entity<Person>().ToTable("Person");
    }
}

public abstract class Person
{
    public int ID { get; set; }

    public string LastName { get; set; }
    public string FirstMidName { get; set; }
}

public class Instructor : Person
{
    public DateTime HireDate { get; set; }
}

public class Student : Person
{
    public DateTime EnrollmentDate { get; set; }
}
  1. Many inherited types in one table
public class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .HasDiscriminator<string>("blog_type")
            .HasValue<Blog>("blog_base")
            .HasValue<RssBlog>("blog_rss");
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

public class RssBlog : Blog
{
    public string RssUrl { get; set; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM