the idea is that some kind of entity may have many images and images may be linked to many entities. In addition each many-to-many relationship has a number for an ordering position.
So here is what my code looks like:
public abstract class X {
public int Id{get; private set;}
public ICollection<ImageLink> ImageLinks{ get; } = new HashSet<ImageLink>();
...
}
public class A : X {
...
}
public class B : X {
...
}
public class <MANY OTHER CLASSES> : X {
...
}
public class ImageLink {
public int EntityId { get; protected set; }
public int ImageId { get; protected set; }
public virtual X Entity { get; protected set; }
public virtual Image Image { get; protected set; }
public int Position { get; private set; }
....
}
I would like my ef core model to have this kind of inheritance because I don't want to repeat some partial views/controllers code and because it makes sense to me.
I know I can't do this because the image link entity will be mapped in a single table but I need a table for each many-to-many relationship.
Any ideas?
You can configure a different image table per entity if you use owned entities
Now, I couldn't get the navigation property to work from ImageLink to X, but it might be possible to do with generics or something.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<A>().OwnsMany(a => a.ImageLinks, e =>
{
e.ToTable("ImageLinksForA");
e.WithOwner();
});
modelBuilder.Entity<B>().OwnsMany(a => a.ImageLinks, e =>
{
// Letting EF pick a table name for me
e.WithOwner();
});
// Repeat for each descendent of X
}
Related
I have an application where the domain has several parent entities each to which a list of Comments are linked in a master-detail fashion.
Instead of having a Comment table for each parent entity's comments, I have opted to have a single Comment table with links to the parent entities.
The reason for this choice is as follows:
As the application expands with more parent entities, I don't need to add a Comment table for each of them
In order to implement a search where the user can search through comments, it is likely to simply search through a single table (likely will use Lucene)
This is illustrated below
Happy to change my mind re this design choice
The link between the parent entity and Comment acts like a many-many relationship. The domain objects are defined as:
public class Customer
{
public Customer(string name)
{
Name = name;
}
protected Customer()
{}
public long Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Comment> Comments { get; }
public void AddComment(Comment comment)
{
Comments.Add(comment);
}
}
public class CustomerComment
{
public long Id { get; set; }
public long CustomerId { get; private set; }
public long CommentId { get; private set; }
}
public class Comment
{
public Comment(long createdByUserId, DateTime createdOnDtm, string content)
{
CreatedByUserId = createdByUserId;
CreatedOnDtm = createdOnDtm;
Content = content;
}
protected Comment()
{}
public long Id { get; private set; }
public long CreatedByUserId { get; init; }
public DateTime CreatedOnDtm { get; init; }
public string Content { get; init; }
public virtual ICollection<Customer> Customers { get; private set; }
//public virtual ICollection<Supplier> Suppliers { get; private set; }
//public virtual ICollection<Other> Others { get; private set; }
}
However when setting up the EF Core model, it seems I have to have the Customers/Suppliers/Others parent entity collections in the Comment domain object
because the relationship looks like a N:M in the relational model even though it is 1:N in the domain model.
This is what the fluent model definition looks like:
modelBuilder.Entity<Customer>()
.HasMany(p => p.Comments)
.WithMany(t => t.Customers)
.UsingEntity<CustomerComment>(
j => j.HasOne<Comment>().WithMany().HasForeignKey(p => p.CommentId),
j => j.HasOne<Customer>().WithMany().HasForeignKey(p => p.CustomerId));
modelBuilder.Entity<Customer>()
.Navigation(p => p.Comments)
.UsePropertyAccessMode(PropertyAccessMode.Property);
modelBuilder.Entity<CustomerComment>()
.HasKey(x => x.Id);
I cannot declare the join type CustomerComment if the Comment does not have the Customers collection. It basically means that my Comment domain object gets 'polluted' with all the possible parent entities
so that EF can understand the link table.
Or is there a way around this?
I'm trying to make a relationship between the Users from the table generated by Asp.Net Identity with my own table. The relationship must be many to many, since many Users can work on the same Task (which is my table), and same time an User can work on multiple Tasks.
public class Task
{
public int ID { get; set; }
public string Name { get; set; }
public string UserID { get; set; }
public virtual ICollection<ApplicationUser> Users { get; set; }
}
public class ApplicationUser : IdentityUser
{
public int TaskID { get; set; }
public virtual ICollection<Task> Tasks{ get; set; }
// rest of the code
}
I try it this way but I get an error during migration (or run time)
"One or more validation errors were detected during model generation:"
Please help me solve this problem and archive what I need.
Try it like this:
public class Projects
{
public Projects()
{
ApplicationUser = new HashSet<ApplicationUser>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }
}
Application User
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
Projects = new HashSet<Projects>();
}
public async Task GenerateUserIdentityAsync(UserManager manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public virtual ICollection <Projects > Projects { get; set; }
}
Application Context :
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public virtual DbSet<Projects> Projects { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
now when I run this Mvc app and register, the db tables I get is like the following:
and the correct schema:
The things to be questioned are a lot, from my point of view important is to determine if you:
- can/should you mix application context and your model context ?
You can try it as shown below using Fluent API.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Task>()
.HasMany<ApplicationUser>(s => s.Users)
.WithMany(c => c.Tasks)
.Map(cs =>
{
cs.MapLeftKey("TaskRefId");
cs.MapRightKey("ApplicationUserRefId");
cs.ToTable("TaskApplicationUser");
});
}
Update : you can see this link too.
EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType
Error text is not related to your many-to-many relationship. It tips that other built-in entities are not configured properly. So, It would be nice if you provided full definition of your custom DbContext-class and how it is configured.
UPDATE
As i understood u are working with two different contexts. You must work with the same context, cause of u are extending IdentityContext, creating relationships and adding custom types. So problem then will be resolved itself.
Hope, this will help.
I am trying to create one-to-many and reverse one-to-one relationship using code first. Here is what I ma trying to do
1) One-to-Many between two classes and it works as expected.
public class X
{
[Key]
public int XId { get; set; }
public ICollection<Y> Y { get; set; }
}
public class Y
{
[Key]
public int YId { get; set; }
public int XId { get; set; }
public X X { get; set; }
}
public class DataContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Y>()
.HasRequired(y => y.X)
.WithMany(x => x.Y)
.HasForeignKey(y => y.XId);
}
}
Now what I want to do is to create Reverse One-to-One optional relationship between Y and X, such that the X will contain a foreign key of Y...How is it possible? Here is what I am trying to do and it throws some Multiplicity Error
public class X
{
[Key]
public int XId { get; set; }
public ICollection<Y> Y { get; set; }
public int YId {get; set; }
[ForiegnKey("YId")]
public Y YOptional { get; set; }
}
public class Y
{
[Key]
public int YId { get; set; }
public int XId { get; set; }
public X X { get; set; }
public X XOptional {get; set; }
}
public class DataContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Y>()
.HasRequired(y => y.X)
.WithMany(x => x.Y)
.HasForeignKey(y => y.XId);
modelBuilder.Entity<X>()
.HasOptional(x => x.YOptional)
.WithOptionalDependent(y=> y.XOptional);
}
}
You can't have a relationship between two entities that is defined differently from either end. So you can't do 1:* from one direction and 1:1 from another.
Let me make a guess that you don't really want it to be 1:1 from the dependent end. From that end it will always only point to one thing.
In mappings, unlike in life, unless you have many to many, a child only has one parent.
You can, however, create a 0..1 : * relationaship (zero or one to many). Where the parent can have one or more children (e.g. "many") but the child can exist without a parent, but it can never have more than one parent (e.g. "zero or one").
Here is the simplest method of making your classes result in a [zero or one] to many relationship. Notice that I made the foreign key in the class Y a nullable int. WIth this setup, EF conventions will result in a mapping that lets a child exist without a parent.
public class X
{
[Key]
public int XId { get; set; }
public ICollection<Y> Y { get; set; }
}
public class Y
{
[Key]
public int YId { get; set; }
public int? XId { get; set; }
public X X { get; set; }
}
public class DataContext : DbContext
{
public DbSet<X> XSet { get; set; }
public DbSet<Y> YSet { get; set; }
}
Here is a screenshot of visual model derived from the above classes and context.
I think this achieves the behavior you are seeking if my guess that you may just be perceiving it differently is correct.
Using the actual class names you mentioned in the comments:
Mapping a User that can have many Singles is not a problem. However, when you want to map a 1:1 association between a User and a Single you have to choose which of the two is the "principle" entity. You can't have a foreign key column in both tables because one entity will always be inserted before the other one. The "dependent" entity is inserted next, and it refers to the principal's primary key value.
So if User is the principal entity, you could have a class model similar to this:
public class User
{
public User()
{
this.Singles = new HashSet<Single>();
}
public int UserId { get; set; }
public string Name { get; set; }
public Single Single { get; set; }
public virtual ICollection<Single> Singles { get; set; }
}
public class Single
{
public int SingleId { get; set; }
public string Name { get; set; }
public virtual User User { get; set; }
public int SuperUserId { get; set; }
public User SuperUser { get; set; }
}
And two options for mappings:
Option 1: User as principal
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasMany(u => u.Singles)
.WithRequired(s => s.SuperUser).HasForeignKey(s => s.SuperUserId);
modelBuilder.Entity<User>().HasOptional(s => s.Single)
.WithOptionalPrincipal(s => s.User).Map(m => m.MapKey("UserId"));
}
In the data model, Single now has two foreign keys, UserId and SuperUserId. This is how to create a User and a Single in User.Single and User.Singles:
var superUser = new User { Name = "superUser1" };
var single = new Single { Name = "single" };
superUser.Singles.Add(single);
db.Users.Add(superUser);
superUser.Single = single;
db.SaveChanges();
And EF will first insert the User, then the Single having both foreign keys equal to the User's primary key.
Option 2: Single as principle
You can also make Single the principal entity in the 1:1 association:
modelBuilder.Entity<User>().HasOptional(s => s.Single)
.WithOptionalDependent(s => s.User).Map(m => m.MapKey("SingleId"));
Now there's only one foreign key in Single (SuperUserId) and a foreign key in User (SingleId). If you execute the same code, now EF will throw
Unable to determine a valid ordering for dependent operations.
This is because there is a chicken-and-egg problem: the Single must be created before the dependent User can be created, but the User must be created before the Single can be added to its Singles collection. This could be solved by assigning the Single later:
var superUser = new User { Name = "superUser1" };
var single = new Single { Name = "single" };
superUser.Singles.Add(single);
db.Users.Add(superUser);
db.SaveChanges();
superUser.Single = single;
db.SaveChanges();
You'd want to wrap this in a TransactionScope, so I think this option is less viable.
Note
As you see, in a 1:1 mapping the foreign key can't be mapped to a property in the class model. There is no HasForeignKey in the fluent API after WithOptionalDependent or WithOptionalPrincipal. Also, this association can only be mapped by the fluent API. In data annotations there is not attribute to indicate the principal end of an association.
From what I understand on several posts the TPT architecure, with EF, does not create the necessary ON DELETE CASCADE when using a shared primary key.... It was also said that the EF context will handle the proper order of deletion of the sub-classed tables (however I do get an error that it breaks the constraint and that I can fix it with adding the ON DELETE CASCADE on the sub-class table)...
more background info...
I have a Section class, which has a number, title, and a list of pages. The page is designed using a super class which holds basic page properties. I have about 10+ sub-classes of the page class. The Section class holds an ICollection of these pages. The DB is created properly with the exception of no ON DELETE CASCADE on the sub-classed tables.
My code will create the entities and adds to the DB fine. However, if I try to delete a section (or all sections) it fails todelete due to the FK constraint on my sub-class page table...
public abstract BaseContent
{
... common properties which are Ignored in the DB ...
}
public class Course : BaseContent
{
public int Id {get;set;}
public string Name {get;set;}
public string Descripiton {get;set;}
public virtual ICollection<Chapter> Chapters{get;set;}
...
}
public class Chapter : BaseContent
{
public int Id {get;set;}
public int Number {get;set;}
public string Title {get;set;}
public virtual Course MyCourse{get;set;}
public virtual ICollection<Section> Sections{get;set;}
...
}
public class Section : BaseContent
{
public int Id {get;set;}
public int Number {get;set;}
public string Title {get;set;}
public virtual Chapter MyChapter {get;set;}
public virtual ICollection<BasePage> Pages {get;set;}
...
}
public abstract class BasePage : BaseContent, IComparable
{
public int Id { get; set; }
public string Title { get; set; }
public string PageImageRef { get; set; }
public ePageImageLocation ImageLocationOnPage { get; set; }
public int PageNumber { get; set; }
public virtual Section MySection { get; set; }
...
}
public class ChapterPage : BasePage
{
public virtual int ChapterNumber { get; set; }
public virtual string ChapterTitle { get; set; }
public virtual string AudioRef { get; set; }
}
public class SectionPage : BasePage
{
public virtual int SectionNumber { get; set; }
public virtual string SectionTitle { get; set; }
public virtual string SectionIntroduction { get; set; }
}
... plus about 8 other BasePage sub-classes...
public class MyContext: DbContext
{
...
public DbSet<Course> Courses { get; set; }
public DbSet<Chapter> Chapters { get; set; }
public DbSet<Section> Sections { get; set; }
public DbSet<BasePage> Pages { get; set; }
...
}
.. Fluent API ... (note Schema is defined to "" for SqlServer, for Oracle its the schema name)
private EntityTypeConfiguration<T> configureTablePerType<T>(string tableName) where T : BaseContent
{
var config = new EntityTypeConfiguration<T>();
config.ToTable(tableName, Schema);
// This adds the appropriate Ignore calls on config for the base class BaseContent
DataAccessUtilityClass.IgnoreAllBaseContentProperties<T>(config);
return config;
}
public virtual EntityTypeConfiguration<BasePage> ConfigurePageContent()
{
var config = configureTablePerType<BasePage>("PageContent");
config.HasKey(pg => pg.Id);
config.HasRequired(pg => pg.Title);
config.HasOptional(pg => pg.PageImageRef);
config.Ignore(pg => pg.ImageLocationOnPage);
return config;
}
public virtual EntityTypeConfiguration<ChapterPage> ConfigureChapterPage()
{
var config = configureTablePerType<ChapterPage>("ChapterPage");
config.HasOptional(pg => pg.AudioRef);
config.Ignore(pg => pg.ChapterNumber);
config.Ignore(pg => pg.ChapterTitle);
return config;
}
public virtual EntityTypeConfiguration<SectionPage> ConfigureSectionPage()
{
var config = configureTablePerType<SectionPage>("SectionPage");
config.HasOptional(pg => pg.AudioRef);
config.Ignore(pg => pg.SectionNumber);
config.Ignore(pg => pg.SectionTitle);
return config;
}
... other code to model other tables...
So the app is able to populate content and the relationships are properly set up. However, when I try to delete the course, I get the error that the delete failed due to the constraint on the ChapterPage to PageContent table..
Here is the code which deletes the Course (actually I delete all courses)...
using (MyContext ctx = new MyContext())
{
ctx.Courses.ToList().ForEach(crs => ctx.Courses.Remove(crs));
AttachLookupEntities(ctx);
ctx.SaveChanges();
}
If I add the 'ON DELETE CASCADE' in the ChapterPage and SectionPage table for its shared primary with PageContent, the delete goes through.
In summary,
The only solution that I have seen is to manually alter the constraints to add the ON DELETE CASCADE for all of my sub-class page tables. I can implement the change, as I have code which generates the DB script for the EF tables I need (a small subset of our whole DB) since we will not use EF to create or instantiate the DB (since it does not properly support migrations as yet...).
I sincerely hope that I have miscoded something, or forgot some setting in the model builder logic. Because if not, the EF designers have defined an architecure (TPT design approach) which cannot be used in any real world situation without a hack workaround. It's a half finished solution. Do not get me wrong, I like the work that has been done, and like most MSFT solutions its works for 70% of most basic application usages. It just is not ready for more complex situations.
I was trying to keep the DB design all within the EF fluent API and self-contained. It's about 98% there for me, just would be nice if they finished the job, maybe in the next release. At least it saves me all the CRUD operations.
Ciao!
Jim Shaw
I have reproduced the problem with a little bit simpler example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;
namespace EFTPT
{
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<BasePage> Pages { get; set; }
}
public abstract class BasePage
{
public int Id { get; set; }
public string Name { get; set; }
public Parent Parent { get; set; }
}
public class DerivedPage : BasePage
{
public string DerivedName { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Parent> Parents { get; set; }
public DbSet<BasePage> BasePages { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent>()
.HasMany(p => p.Pages)
.WithRequired(p => p.Parent); // creates casc. delete in DB
modelBuilder.Entity<BasePage>()
.ToTable("BasePages");
modelBuilder.Entity<DerivedPage>()
.ToTable("DerivedPages");
}
}
class Program
{
static void Main(string[] args)
{
using (var ctx = new MyContext())
{
var parent = new Parent { Pages = new List<BasePage>() };
var derivedPage = new DerivedPage();
parent.Pages.Add(derivedPage);
ctx.Parents.Add(parent);
ctx.SaveChanges();
}
using (var ctx = new MyContext())
{
var parent = ctx.Parents.FirstOrDefault();
ctx.Parents.Remove(parent);
ctx.SaveChanges(); // exception here
}
}
}
}
This gives the same exception that you had too. Only solutions seem to be:
Either setup cascading delete for the TPT constraint in the DB manually, as you already tested (or put an appropriate SQL command into the Seed method).
Or load the entites which are involved in the TPT inheritance into memory. In my example code:
var parent = ctx.Parents.Include(p => p.Pages).FirstOrDefault();
When the entities are loaded into the context, EF creates actually two DELETE statements - one for the base table and one for the derived table. In your case, this is a terrible solution because you had to load a much more complex object graph before you can get the TPT entities.
Even more problematic is if Parent has an ICollection<DerivedPage> (and the inverse Parent property is in DerivedPage then):
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<DerivedPage> Pages { get; set; }
}
public abstract class BasePage
{
public int Id { get; set; }
public string Name { get; set; }
}
public class DerivedPage : BasePage
{
public string DerivedName { get; set; }
public Parent Parent { get; set; }
}
The example code wouldn't throw an exception but instead delete the row from the derived table but not from the base table, leaving a phantom row which cannot represent an entity anymore because BasePage is abstract. This problem is not solvable by a cascading delete but you were actually forced to load the collection into the context before you can delete the parent to avoid such a nonsense in the database.
A similar question and analysis was here: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/3c27d761-4d0a-4704-85f3-8566fa37d14e/
Confusing Situation
I have a situation where I have 2 entities where 1 inherits from the other, that need to map to 2 separate tables, but code use should be around the base of the 2 entities.
Details
public class Team
{
public virtual int Id { get; set; }
public virtual ICollection<Employee> Members { get; set; }
}
public class Employee
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Team> Teams { get; set; }
}
public class EmployeeInfo : Employee
{
public virtual int Id { get; set; }
public virtual decimal Amount { get; set; }
}
We have an existing database schema where Employee and EmployeeInfo are separate tables with a FK between EmployeeInfo_Id and Employee_Id.
In our system "managers" will be adding Employee's to the system, with a set of private information (more properties than listed above) like pay, and add them to a Team. Other areas of the system will be using the Team or Employee objects for various other things. We would like to have to code super simple if the mapping can be done.
When a manager creates a new employee we would like the code to look something like this:
public void Foo(string name, decimal pay)
{
// create the employee
var employee = new EmployeeInfo();
employee.Name = name;
employee.Pay = pay;
// add him/her to the team
_team.Employees.Add(employee); // the idea being that consumers of the Team entity would not get the separate employee info properties
// save the context
_context.SaveChanges();
}
The end result would be that the EmployeeInfo properties entered into the EmployeeInfo table and the base Employee data is entered into the Employee table and added to the Team via the association table TeamEmployees.
So far I'm trying the current mappings, and I get an invalid column named "Discriminator." When just adding an employee to a team.
public class TeamConfiguration : EntityTypeConfiguration<Team>
{
public TeamConfiguration()
{
ToTable("Team");
HasKey(t => t.Id);
HasMany(t => t.Members).WithMany(m => m.Teams)
.Map(m =>
{
m.MapLeftKey("Team_Id");
m.MapRightKey("Employee_Id");
m.ToTable("TeamEmployees");
});
}
}
public class EmployeeConfiguration : EntityTypeConfiguration<Employee>
{
public EmployeeConfiguration()
{
ToTable("Employee");
ToTable("EmployeeInfo");
HasKey(t => t.Id);
Property(p => p.Name);
HasMany(m => m.Teams)
.WithMany(t => t.Members)
.Map(m =>
{
m.MapLeftKey("Employee_Id");
m.MapRightKey("Team_Id");
m.ToTable("TeamEmployees");
});
}
}
Also, if I take the many-to-many between team and employee out of the mix I get a FK exception on Employee_Id to EmployeeInfo_Id.
Thanks, JR.
Discriminator is a column that's being added to your table when you use Table Per Hierarchy approach.
I think what you're looking for is "Table per Type (TPT)". Decorate your EmployeeInfo class as follows:
[Table("EmployeeInfo")]
public class EmployeeInfo : Employee
Or add below to your OnModelCreating event:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
...
modelBuilder.Entity<EmployeeInfo>().ToTable("EmployeeInfo");
...
}
Or, create the following class and use it like modelBuilder.Configurations.Add(new EmployeeInfoConfiguration()); in OnModelCreating method:
public class EmployeeInfoConfiguration : EntityTypeConfiguration<EmployeeInfo>
{
public EmployeeInfoConfiguration()
{
ToTable("EmployeeInfo");
}
}
This will cause EF to create EmployeeInfo table with necessary constraints.
Also, it's good to initialize your collections in your objects' constructors to prevent null exception. For example in Team class:
public Team()
{
this.Employees = new HashSet<Employee>();
}
I copied your code exactly, and changed the following parts:
public class Team
{
public Team()
{
this.Members = new HashSet<Employee>();
}
public virtual int Id { get; set; }
public virtual ICollection<Employee> Members { get; set; }
}
public class Employee
{
public Employee()
{
this.Teams = new HashSet<Team>();
}
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Team> Teams { get; set; }
}
[Table("EmployeeInfo")]
public class EmployeeInfo : Employee
{
public virtual int Id { get; set; }
public virtual decimal Amount { get; set; }
}
In the DbContext, no changes:
public partial class TestEntities : DbContext
{
public DbSet<Employee> Employees { get; set; }
public DbSet<EmployeeInfo> Employee_Info { get; set; }
public DbSet<Team> Teams { get; set; }
}
and your working Foo method:
public static void Foo(string name, decimal pay)
{
var _team = new Team();
var context = new TestEntities();
context.Teams.Add(_team);
// create the employee
var employee = new EmployeeInfo();
employee.Name = name;
employee.Amount = pay;
context.Employees.Add(employee);
context.SaveChanges();
// add him/her to the team
_team.Members.Add(employee);
// save the context
context.SaveChanges();
}
Finally, remove ToTable("EmployeeInfo"); part from EmployeeConfiguration since you have mentioned this correctly in your mode creating event.
For more info about Table Per Type approach, check out this great article.