Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 201
Bruno Henri Avatar asked Dec 09 '17 21:12

Bruno Henri


People also ask

What is table Per hierarchy in Entity Framework?

Table per Hierarchy (TPH): This approach suggests one table for the entire class inheritance hierarchy. The table includes a discriminator column which distinguishes between inheritance classes. This is a default inheritance mapping strategy in Entity Framework.

How do I display a table in Entity Framework?

Right-click the Models folder in the Solution Explorer window and the select the menu option Add, New Item. Select the Data category and select the ADO.NET Entity Data Model template. Give your data model the name MoviesDBModel.

Does Entity Framework create tables?

If you're using a Code First approach then Entity Framework will build the table for you. It looks like you are not using Code First, so you will have create the table in the database.

Should I use EF6 or EF core?

Keep using EF6 if the data access code is stable and not likely to evolve or need new features. Port to EF Core if the data access code is evolving or if the app needs new features only available in EF Core. Porting to EF Core is also often done for performance.


1 Answers

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.

like image 53
LuckyLikey Avatar answered Sep 28 '22 21:09

LuckyLikey