I have a program using Entity Framework (EF) Database First in the data access layer. I know that in order for EF to auto-generate the navigation properties of a many to many relationship, the mapping table needs to contain only a composite primary key:
Project
- ProjectId (PK)
- Name
ContentType
- ContentTypeId (PK)
- Name
ProjectContentTypeMapping
- ProjectId (PK)
- ContentTypeId (PK)
In this case everything works fine, and I can access Projects from ContentTypes and the other way around with navigation properties.
However I have a requirement to have extra fields that are particular to the relation between Projects and ContentTypes, and that would be extra columns in the ProjectContentTypeMapping table. Once I add these I loose the navigation properties, and EF shows the mapping table in the designer.
Is there any way I can manually configure the mapping between these two tables in EF (Database First)? Alternatively, how can I represent this? I was thinking of maybe having an extra "metadata" table with a FK to the mapping table, but it looks "hacky" to me...
Thanks
Many-to-many relationships require a collection navigation property on both sides. They will be discovered by convention like other types of relationships. The way this relationship is implemented in the database is by a join table that contains foreign keys to both Post and Tag .
Step 1 – Add foreign key property to other entities, in the joining entity. Step 2 – Add collection navigation property on the other entities towards the joining entity. Step 3 – Next create DB Context OnModelCreating() method configure both the foreign keys in the joining entity as a composite key using Fluent API.
No, you cannot have extra columns in your mapping table in entity framework. Because, having an extra column implies you intend to use it, but Mapping tables are not part of the entity, so, entity framework, no longer treats your mapping table with extra columns as a Mapping table. You will have to manipulate the Mappings manually.
Lets take example of your classes:
Project
- ProjectId (PK)
- Name
- ProjectContents
ContentType
- ContentTypeId (PK)
- Name
- ProjectContents
ProjectContentTypeMapping
- ProjectId (PK)
- ContentTypeId (PK)
- OtherRelevantColumn
where ProjectContents is of type ProjectContentTypeMapping
so whenever you add a Project with Certain ContentType, you would be doing this:
Project prj = new Project();
//fill out scalar properties
ProjectContentTypeMapping pctm = new ProjectContentTypeMapping();
pctm.ContentTypeId = 1; //or whatever you want, or selected from UI
prj.ProjectContents = new ProjectContentTypeMapping();
prj.ProjectContents.Add(pctm);
dataContext.Projects.Add(prj);
Now in case of editing (adding ContentTypes) to an existing project, you won't do prj.ProjectContents = new ...
rather, you would do it only when it is null i,e,
if(prj.ProjectContents==null)
prj.ProjectContents = new ProjectContentTypeMapping();
also, one very very important thing, since now your ProjectContentTypeMapping is no longer a mapping table, so, deleting a Project would give you an error, if its id is being present in ProjectContentTypeMapping table; you will have to remove them manually i.e
foreach(var pctm in prj.ProjectContents.ToList())
{
prj.ProjectContents.Remove(pctm);
datacontext.ProjectContentTypeMappings.Remove(pctm);
}
datacontext.Remove(prj);
datacontext.SaveChanges();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With