Entity Framework Core Many-to-Many Resolve Ambiguity - entity-framework

What is the effective way to resolve ambiguity of many-to-many relationships that point to the same entity either through annotations or fluent configuration? Given models such as:
public class Team
{
public int TeamId { get; set; }
public string Name { get; set; }
// Teams can be owned by multiple users
public List<User> Owners { get; set; }
// Teams can have multiple members
public List<User> Members { get; set; }
}
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
// User can own zero to many teams
public List<Team> Owners { get; set; }
// User can be a member of zero to many teams
public List<Team> Members { get; set; }
}
Scaffolding results in an error along the lines of "Unable to determine the relationship by navigation "Team.Owners" of type "List".
Is this something that can be effectively resolved by manually creating join entities such as TeamOwner and TeamMember or would EF Core still struggle with ambiguity?
Thanks for any help you can provide.

You have two Navigation properties on each entity, and EF doesn't have a convention to identify which goes with which. So you need to configure the model to explicitly relate the navigation properties. You'll also want to pick a descriptive name for the linking table. EG:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Team>()
.HasMany(t => t.Owners)
.WithMany(o => o.OwnerOf)
.UsingEntity(j => j.ToTable("TeamOwners"));
modelBuilder.Entity<Team>()
.HasMany(t => t.Members)
.WithMany(o => o.MemberOf)
.UsingEntity(j => j.ToTable("TeamMembers"));
base.OnModelCreating(modelBuilder);
}
You can relate the navigation properties with annotations, but can't name the linking table. eg
public class Team
{
public int TeamId { get; set; }
public string Name { get; set; }
[InverseProperty(nameof(User.OwnerOf))]
public List<User> Owners { get; set; }
[InverseProperty(nameof(User.MemberOf))]
public List<User> Members { get; set; }
}

Related

EF Core - Don't know how to config 1 - N in same entity 2 times

The context is : A Student can make appointments to Mentor and Mentor can have many appointments. Mentor may be student or lecturer.
I don't separate Student and Mentor but merge them into one entities User
public class User
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Avatar { get; set; }
public string MeetUrl { get; set; }
public bool? IsMentor { get; set; }
public bool IsActive { get; set; }
public ICollection<Appointment> Appointments { get; set; }
}
public class Appointment
{
public string Id { get; set; }
public string StudentId { get; set; }
public User Student { get; set; }
public string MentorId { get; set; }
//public User Mentor { get; set; }
public bool IsApproved { get; set; }
}
I don't know how to config the relation of these entities with fluent-api to fit with the context.
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Appointment>()
.HasOne<User>(a => a.Student)
.WithMany(st => st.Appointments)
.HasForeignKey(st => st.StudentId);
builder.Entity<Appointment>()
.HasOne<User>(a => a.Mentor)
.WithMany(m => m.Appointments)
.HasForeignKey(a => a.MentorId);
}
Should I separate User into 2 entities Student, Mentor?
What you are trying to do here with fluent syntax is set up "navigation properties".
Consider the following piece your code:
builder.Entity<Appointment>()
.HasOne<User>(a => a.Student)
.WithMany(st => st.Appointments)
.HasForeignKey(st => st.StudentId);
Here you are saying Appointments and User have a one-to-many relation where StudentId is your FK and Student represents the one User item this relation is linked to. You are also saying Appointments represents that many appointments that are linked to the User record the via the FK StudentId.
In other words, in this piece of code, you have specified that Appointments represents all the appointments of the current User as a student and not as a mentor. However, in the next fluent syntax, you are similarly trying to set the same property Appointments to represent the list of appointments that the current user has as a mentor.
You can't have the same property for both these use cases. You would need two properties in your User table like AppointmentsAsStudent and AppointmentsAsMentor.

Entity Framework Core DbSet is not returning any data from database

Entity Framework Core DbSet is not returning any data from database, but the database has many register.
This is the entity
public class Entity : BaseEntity
{
public int EntityStatusId { get; set; }
public int AddressId { get; set; }
public string Name { get; set; }
public string SocialReason { get; set; }
public string CNPJ { get; set; }
public EntityType Type { get; set; }
public DateTime? CreationDate { get; set; }
public bool? ReceiptDisabled { get; set; }
public EntityStatus EntityStatus { get; set; }
public Address Address { get; set; }
public List<Company> Companies { get; set; }
public List<Role> RoleList { get; set; }
}
public abstract class BaseEntity
{
public int Id { get; set; }
}
Now this is the configuration class.
public class EntityMap : IEntityTypeConfiguration<Entity>
{
public void Configure(EntityTypeBuilder<Entity> builder)
{
builder.ToTable("Entity");
builder.HasKey(entity => entity.Id);
builder
.Property(entity => entity.EntityStatusId);
builder
.Property(entity => entity.AddressId);
builder
.Property(entity => entity.Name);
builder
.Property(entity => entity.SocialReason);
builder
.Property(entity => entity.CNPJ);
builder
.Property(entity => entity.Type)
.HasConversion(x => (int)x, x => (EntityType)x);
builder
.Property(entity => entity.CreationDate);
builder
.Property(entity => entity.ReceiptDisabled);
builder
.HasOne(entity => entity.EntityStatus);
builder
.HasOne(entity => entity.Address);
builder
.HasMany(entity => entity.RoleList)
.WithOne(x => x.Entity);
builder
.HasMany(entity => entity.Companies)
.WithOne(x => x.Entity);
}
}
And the context class.
public class AucContext : DbContext
{
public AucContext(string databaseConfiguration)
{
_databaseConfiguration = databaseConfiguration;
}
private readonly string _databaseConfiguration;
public DbSet<Campaign> Campaigns { get; set; }
public DbSet<CampaignProject> CampaignProjects { get; set; }
public DbSet<Company> Companies { get; set; }
public DbSet<Cart> Carts { get; set; }
public DbSet<CartItem> CartItems { get; set; }
public DbSet<Donation> Donations { get; set; }
public DbSet<DonationRecurrencePeriod> DonationRecurrencePeriods { get; set; }
public DbSet<Entity> Entities { get; set; }
public DbSet<Institution> Institutions { get; set; }
public DbSet<PaymentMethod> PaymentMethods { get; set; }
public DbSet<Person> People { get; set; }
public DbSet<Project> Projects { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new CampaignMap());
modelBuilder.ApplyConfiguration(new CampaignProjectMap());
modelBuilder.ApplyConfiguration(new CompanyMap());
modelBuilder.ApplyConfiguration(new CartMap());
modelBuilder.ApplyConfiguration(new CartItemMap());
modelBuilder.ApplyConfiguration(new DonationMap());
modelBuilder.ApplyConfiguration(new DonationRecurrencePeriodMap());
modelBuilder.ApplyConfiguration(new EntityMap());
modelBuilder.ApplyConfiguration(new InstitutionMap());
modelBuilder.ApplyConfiguration(new PaymentMethodMap());
modelBuilder.ApplyConfiguration(new PersonMap());
modelBuilder.ApplyConfiguration(new ProjectMap());
modelBuilder.ApplyConfiguration(new UserMap());
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_databaseConfiguration);
}
}
And the query was simple
var entity = context.Entities.Find(3)
this simple query is returning nothing, any ideas for what is happening?
Update
I have updated somethings since yesterday, and now i have updated the question unfortunately still don't work
OBS:. The ConnectionString it's ok, other objects just work fine.
First, add Id to your Entity:
public int Id { get; set; }
Then in your DbContext:
1:In your OnModelCreating,add
modelBuilder.ApplyConfiguration(new EntityMap());
2:Add DbSet:
public DbSet<Entity> Entity { get; set; }
Re-migrate and update the database.Your code will work fine.
An interesting problem if some entities work but this one doesn't. There are a couple additional things to check/try:
Ensure you have no duplicate mappings. For example, if your Entity has a HasMany.WithOne relationship with another entity, ensure that the mapping for that other entity does not declare a HasOne.WithMany or other relationship back to Entity. This can cause weird behaviour.
Your HasOne relationships are missing WithMany and FK declarations. Given you are using "Id" as a base inherited PK on your entities you should consider explicitly declaring your FK relationships. The WithMany declaration is optional in EFCore, however it is needed to declare the FK if it doesn't follow convention. (and I'm no fan of convention for just deciding not to work)
builder
.HasOne(entity => entity.EntityStatus)
.WIthMany()
.HasForeignKey(entity => entity.EntityStatusId);
builder
.HasOne(entity => entity.Address);
.WIthMany()
.HasForeignKey(entity => entity.AddressId);
EF should be working out the FK names by convention though. Just keep in mind that EF conventions follow the type name, not property name so for instance something like this:
public User CreatedBy { get; set; }
by convention would be looking for a FK property of UserId rather than CreatedById which can lead to weird behaviour or errors.
On a side note you do not need to declare .Property() for each property in an entity, only for properties that require some special configuration like IdentityColumn, NotMapped (ignore) or specifying a data constraint / length etc. I would also recommend removing the .Property() statement for any FK columns in your entity
This all said, I've tinkered with a test EF Core project setting up duplicate mapping between objects and leaving off WithMany() and FK declarations and I was not able to reproduce your issue. I think there is something very specific to your schema or mapping that is tripping up EF to resolve this "Entity" object. If these changes do not work, take it down to the minimum viable object and remove all related entity mappings, setting them all to NotMapped so-as not to break your code and then try loading your Entity objects. From there re-introduce the relationships one by one until it stops loading them and narrow it down. If you do identify a rogue mapping responsible, do be sure to post an update with details about the culprit because it would probably be useful in case someone else gets tripped up by it.

How can I name a navigation property a different name from it's entity name in my EF POCO?

I have a POCO Entity named Employee.
And then I have a second POCO Entity named Case.
I want a navigation property that looks like instead this:
public class Case : BaseEntity
{
public long EmployeeId { get; set; }
public virtual Employee Employee{ get; set; }
like this:
public class Case : BaseEntity
{
public long InitialContactId { get; set; }
public virtual Employee InitialContact { get; set; }
I want to name my property InitialContact. Not Employee.
But I get this error when EF tries to create the Database:
Unable to determine the relationship represented by navigation property 'Case.InitialContact' of type 'Employee'. Either manually configure the relationship, or ignore this property from the model.
Update 1:
I got it to work like this:
public class Case : BaseEntity
{
public long InitialContactId { get; set; }
[ForeignKey("Id")]
public virtual Employee InitialContact { get; set; }
public DateTime InitalConsultDate { get; set; }
public Guid AppUserId { get; set; }
public virtual AppUser LerSpecialist { get; set; }
}
The primary key is ID in my BaseEntity. Not EmployeeId.
But I have second part to my question.
Here is my Complete Employee POCO:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using Hrsa.Core.Generic.Model.Framework.Concrete;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace Hrsa.Core.Generic.Model.Lerd
{
public class Employee : BaseEntity
{
[BindNever]
public string Email { get; set; }
[BindNever]
public long OrganizationId { get; set; }
[BindNever]
public string Supervisor { get; set; }
[BindNever]
public string SupervisorEmail { get; set; }
[BindNever]
public string FirstName { get; set; }
[BindNever]
public string LastName { get; set; }
public string Notes { get; set; }
[BindNever]
public long BargainingUnitId { get; set; }
[BindNever]
public long PayPlanId { get; set; }
[BindNever]
public long GradeRankId { get; set; }
[BindNever]
public long PositionTitleId { get; set; }
[BindNever]
public long SeriesId { get; set; }
public bool IsUnionEmployee { get; set; }
public virtual Organization Organization { get; set; }
public virtual BargainingUnit BargainingUnit { get; set; }
public virtual PayPlan PayPlan { get; set; }
public virtual GradeRank GradeRank { get; set; }
public virtual PositionTitle PositionTitle { get; set; }
public virtual Series Series { get; set; }
public virtual ICollection<UnionHours> UnionHours { get; set; }
public virtual ICollection<Case> Cases { get; set; }
[NotMapped]
public string UnionEmployeeYesNo => (IsUnionEmployee) ? "Yes" : "No";
}
}
I want my Employee to have many Cases:
public virtual ICollection<Case> Cases { get; set; }
Here is my complete Cases POCO:
public class Case : BaseEntity
{
public long InitialContactId { get; set; }
[ForeignKey("Id")]
public virtual Employee InitialContact { get; set; }
public DateTime InitalConsultDate { get; set; }
public Guid AppUserId { get; set; }
public virtual AppUser LerSpecialist { get; set; }
}
So now my DB looks like this:
So I have my InitialContactId in Cases ok.
But now I need my Case to have many Employees.
So I add this in to my Case POCO:
public virtual ICollection<Employee> Employees { get; set; }
Now it looks like this:
public class Case : BaseEntity
{
public long InitialContactId { get; set; }
[ForeignKey("Id")]
public virtual Employee InitialContact { get; set; }
public DateTime InitalConsultDate { get; set; }
public Guid AppUserId { get; set; }
public virtual AppUser LerSpecialist { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
Now when I run it, I get this error again:
Unable to determine the relationship represented by navigation property 'Case.InitialContact' of type 'Employee'. Either manually configure the relationship, or ignore this property from the model.
Update 2:
I found this article for a Many-Many relationship in .Net Core 1:
http://www.learnentityframeworkcore.com/configuration/many-to-many-relationship-configuration
So now I have a bridge lookup entity:
public class EmployeeCase
{
[ForeignKey("Id")]
public long EmployeeId { get; set; }
public Employee Employee { get; set; }
[ForeignKey("Id")]
public long CaseId { get; set; }
public Case Case { get; set; }
}
Employee POCO:
Changed:
public virtual ICollection<Case> Cases { get; set; }
to:
// Mapping - Collection of Cases
public virtual ICollection<EmployeeCase> EmployeeCases { get; set; }
Case POCO:
Changed:
public virtual ICollection<Employee> Employees { get; set; }
to:
// Mapping - Collection of Employees
public virtual ICollection<EmployeeCase> EmployeeCases { get; set; }
In my AppDbContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
#region Many-to-Many Employees Cases
modelBuilder.Entity<EmployeeCase>()
.HasKey(ec => new { ec.EmployeeId, ec.CaseId });
modelBuilder.Entity<EmployeeCase>()
.HasOne(ec => ec.Employee)
.WithMany(e => e.EmployeeCases)
.HasForeignKey(ec => ec.EmployeeId);
modelBuilder.Entity<EmployeeCase>()
.HasOne(ec => ec.Case)
.WithMany(c => c.EmployeeCases)
.HasForeignKey(ec => ec.CaseId);
#endregion
}
Now when I run I get this error:
An exception of type 'System.Data.SqlClient.SqlException' occurred in Microsoft.EntityFrameworkCore.Relational.dll but was not handled in user code
Additional information: Introducing FOREIGN KEY constraint 'FK_EmployeeCase_Employees_EmployeeId' on table 'EmployeeCase' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.
Update 3:
Finally got my tables the way I want with this piece of code from:
Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Get rid of Cascading Circular error on ModelBuilding
foreach (var relationShip in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
relationShip.DeleteBehavior = DeleteBehavior.Restrict;
}
#region Many-to-Many Employees Cases
modelBuilder.Entity<EmployeeCase>()
.HasKey(ec => new { ec.EmployeeId, ec.CaseId });
modelBuilder.Entity<EmployeeCase>()
.HasOne(ec => ec.Employee)
.WithMany(e => e.EmployeeCases)
.HasForeignKey(ec => ec.EmployeeId);
modelBuilder.Entity<EmployeeCase>()
.HasOne(ec => ec.Case)
.WithMany(c => c.EmployeeCases)
.HasForeignKey(ec => ec.CaseId);
#endregion
base.OnModelCreating(modelBuilder);
}
Update 4:
This did not work after all.
Remvoving the delete behavior for everything messes up my other relationships and I get errors.
How can I fix this?
This is disgusting.
So wishing I did not go Core.
Entity Framework uses conventions to guess how to map your C# model to database objects.
In your case you violate convention by custom name, so you should explain Entity Framework how to map this stuff.
There are two possible ways: attributes and fluent API. I'd suggest to use the latter one.
See section "Configuring a Foreign Key Name That Does Not Follow the Code First Convention" here: Entity Framework Fluent API - Relationships
I have made it a habit of explicitly defining my relationships as EF does not always get them the way I want. I like to create a Mapping folder that contains my entity maps. The fluent api works great for this and inherits from EntityTypeConfiguration.
Try this.
public class CaseMap : EntityTypeConfiguration<Case>
{
public CaseMap()
{
HasKey(m => m.Id)
HasRequired(m => m.InitialContact)
.WithMany(e => e.Cases)
.HasForeignKey(m => m.InitialContactId);
}
}
Almost forgot. You need to tell your DbContext where to find these mappings. Add this to your DbContexts OnModelCreating method.
modelBuilder.Configurations.AddFromAssembly(typeof(MyContext).Assembly);
This is what worked finally for the Cascading Delete circular references on the many-to-many in EF Core:
// Get rid of Cascading Delete Circular references error.
var type = modelBuilder.Model.GetEntityTypes().Single(t => t.Name == "Hrsa.Core.Generic.Model.Lerd.EmployeeCase");
foreach (var relationship in type.GetForeignKeys())
{
relationship.DeleteBehavior = DeleteBehavior.Restrict;
}
You have to get the Entity representing the many to many lookup only.
And from there restrict the DeleteBehavior.

configure many to many relationship in entity framework

So following this example:
http://www.entityframeworktutorial.net/code-first/configure-many-to-many-relationship-in-code-first.aspx
I have a Student class:
public class Student
{
public Student() { }
public int StudentId { get; set; }
public string StudentName { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
and a Course class
public class Course
{
public Course()
{
this.Students = new HashSet<Student>();
}
public int CourseId { get; set; }
public string CourseName { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
They have Many-to-Many relationship which is configured this way:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().HasMany<Course>(s => s.Courses).WithMany(c => c.Students).Map(c =>
{
c.MapLeftKey("Student_id");
c.MapRightKey("Course_id");
c.ToTable("StudentAndCourse");
});
base.OnModelCreating(modelBuilder);
}
I have created the models and tables myself and map to them. So far so good. The problem is I do not need the collection of related Students to my courses. In other words when I get my courses they are coming with their related Students. I need the Students with the assigned Courses but when I get the courses through my repo, I need only them.
I tried to remove the Students collection from my Course class but was enable to fix the mapping. I am not experienced with EF and any help with working example will be greatly appreciated.
There is WithMany() method which does not require navigation property for related entities:
modelBuilder.Entity<Student>()
.HasMany(s => s.Courses)
.WithMany()
.Map(c =>
{
c.MapLeftKey("Student_id");
c.MapRightKey("Course_id");
c.ToTable("StudentAndCourse");
});

MVC EF code first creating model class

I'm new to MVC and EF code first. I'm in struggle to model a real-estate company DB model using EF code-first approach and I did some exercises as well as reading some online tutorials.
First thing I have a customers table that would be in relation with one or more properties he/she has registered as it's owner to sell or to rent, I was wondering if it is possible to have some sub classes inside a model class for registered properties as below:
public Property
{
public int PropertyID { get; set; }
public bool IsforSale { get; set; }
public bool IsforRent { get; set; }
public class Apartment{
public int ApartmentID { get; set; }
public int AptSqureMeter { get; set; }
. . .
. . .
}
public class Villa{
public int VillaID { get; set; }
public int VillaSqureMeter { get; set; }
. . .
. . .
}
and also other sub-classes for other types of properties
}
If the answer is Yes, then how should I declare the relations using data annotation or Fluent API, and then please help me how to update both Customers table and Property table with the customer information and property info at the same time?
thanks for your answer in advance.
As #Esteban already provided you with a pretty detailed answer on how to design your POCOs and manage the relationship between them, I will only focus on that part of your question:
how should I declare the relations using data annotation or Fluent API
First of all, you should know that certain model configurations can only be done using the fluent API, here's a non exhaustive list:
The precision of a DateTime property
The precision and scale of numeric properties
A String or Binary property as fixed-length
A String property as non-unicode
The on-delete behavior of relationships
Advanced mapping strategies
That said, I'm not telling you to use Fluent API instead of Data Annotation :-)
As you seem to work on an MVC application, you should keep in mind that Data Annotation attributes will be understood and processed by both by Entity Framework and by MVC for validation purposes. But MVC won't understand the Fluent API configuration!
Both your Villa and Apartment classes have similar properties, if they are the same but as it's type, you could create an enum for that.
public enum PropertyType {
Apartment = 1,
Villa
}
public class Property {
public int PropertyID { get; set; }
public bool IsforSale { get; set; }
public bool IsforRent { get; set; }
public PropertyType PropertyType { get; set; }
public int SquareMeter { get; set; }
}
This way of modelating objects is refered as plain old clr object or POCO for short.
Assume this model:
public class User {
public int UserId { get; set; }
public string Username { get; set; }
public virtual List<Role> Roles { get; set; }
}
public class Role {
public int RoleId { get; set; }
public string Name { get; set; }
public virtual List<User> Users { get; set; }
}
Creating relations with fluent api:
Mapping many to many
On your OnModelCreating method (you'll get this virtual method when deriving from DbContext):
protected override void OnModelCreating(DbModelBuilder builder) {
// Map models/table
builder.Entity<User>().ToTable("Users");
builder.Entity<Role>().ToTable("Roles");
// Map properties/columns
builder.Entity<User>().Property(q => q.UserId).HasColumnName("UserId");
builder.Entity<User>().Property(q => q.Username).HasColumnName("Username");
builder.Entity<Role>().Property(q => q.RoleId).HasColumnName("RoleId");
builder.Entity<Role>().Property(q => q.Name).HasColumnName("Name");
// Map primary keys
builder.Entity<User>().HasKey(q => q.UserId);
builder.Entity<Role>().HasKey(q => q.RoleId);
// Map foreign keys/navigation properties
// in this case is a many to many relationship
modelBuilder.Entity<User>()
.HasMany(q => q.Roles)
.WithMany(q => q.Users)
.Map(
q => {
q.ToTable("UserRoles");
q.MapLeftKey("UserId");
q.MapRightKey("RoleId");
});
Mapping different types of relationships with fluent api:
One to zero or one:
Given this model:
public class MenuItem {
public int MenuItemId { get; set; }
public string Name { get; set; }
public int? ParentMenuItemId { get; set; }
public MenuItem ParentMenuItem { get; set; }
}
And you want to express this relationship, you could do this inside your OnModelCreating method:
builder.Entity<MenuItem>()
.HasOptional(q => q.ParentMenuItem)
.WithMany()
.HasForeignKey(q => q.ParentMenuItemId);
One to many
Given this model:
public class Country {
public int CountryId { get; set; }
public string Name { get; set; }
public virtual List<Province> Provinces { get; set; }
}
public class Province {
public int ProvinceId { get; set; }
public string Name { get; set; }
public int CountryId { get; set; }
public Country Country { get; set; }
}
You now might want to express this almost obvious relationship. You could to as follows:
builder.Entity<Province>()
.HasRequired(q => q.Country)
.WithMany(q => q.Provinces)
.HasForeignKey(q => q.CountryId);
Here are two useful links from MSDN for further info:
Configuring Relationships with the Fluent API.
Code First Relationships Fluent API.
EDIT:
I forgot to mention how to create a many to many relationship with additional properties, in this case EF will NOT handle the creation of the join table.
Given this model:
public class User {
public int UserId { get; set; }
public string Username { get; set; }
public virtual List<Role> Roles { get; set; }
pubilc virtual List<UserEmail> UserEmails { get; set; }
}
pubilc class Email {
public int EmailId { get; set; }
public string Address { get; set; }
public List<UserEmail> UserEmails { get; set; }
}
public class UserEmail {
public int UserId { get; set; }
public int EmailId { get; set; }
public bool IsPrimary { get; set; }
public User User { get; set; }
public Email Email { get; set; }
}
Now that we've added a new property into our join table ef will not handle this new table.
We can achieve this using the fluent api in this case:
builder.Entity<UserEmail>()
.HasKey( q => new {
q.UserId, q.EmailId
});
builder.Entity<UserEmail>()
.HasRequired(q => q.User)
.WithMany(q => q.UserEmails)
.HasForeignKey(q => q.EmailId);
builder.Entity<UserEmail>()
.HasRequired(q => q.Email)
.WithMany(q => q.UserEmails)
.HasForeignKey(q => q.UserId);