Reputation: 373
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
Table HeadOffice
Table BranchOffice
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!
Upvotes: 6
Views: 10364
Reputation: 3850
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.
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.
Upvotes: 4
Reputation: 4200
You can find an answer here https://learn.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://learn.microsoft.com/en-us/ef/core/modeling/relational/inheritance
Copying the code here just in case microsoft used to mess with urls and docs
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; }
}
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; }
}
Upvotes: -2