我有一个程序在数据访问层使用Entity Framework(EF)Database First。我知道为了让EF自动生成多对多关系的导航属性,映射表只需要包含一个复合主键:
Project
- ProjectId (PK)
- Name
ContentType
- ContentTypeId (PK)
- Name
ProjectContentTypeMapping
- ProjectId (PK)
- ContentTypeId (PK)
在这种情况下,一切正常,我可以从ContentTypes访问项目,反过来使用导航属性。
但是,我需要有一些额外的字段,这些字段特别适用于Projects和ContentTypes之间的关系,而这将是ProjectContentTypeMapping表中的额外列。一旦我添加了这些,我就会松开导航属性,EF会在设计器中显示映射表。
有没有办法在EF(数据库优先)中手动配置这两个表之间的映射?或者,我该如何表示?我在考虑可能有一个带有FK的额外“元数据”表到映射表,但它对我来说看起来很“hacky”......
由于
答案 0 :(得分:7)
不,您不能在实体框架中的映射表中包含额外列。 因为,有一个额外的列暗示您打算使用它,但Mapping表不是实体的一部分,因此,实体框架不再将具有额外列的映射表视为Mapping表。您必须手动操作映射。
让我们举例说明你的课程:
Project
- ProjectId (PK)
- Name
- ProjectContents
ContentType
- ContentTypeId (PK)
- Name
- ProjectContents
ProjectContentTypeMapping
- ProjectId (PK)
- ContentTypeId (PK)
- OtherRelevantColumn
其中ProjectContents的类型为ProjectContentTypeMapping
因此,无论何时添加具有某些ContentType的项目,您都会这样做:
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);
现在在编辑(添加ContentTypes)到现有项目的情况下,你不会做prj.ProjectContents = new ...
而是只有当它为null时才会这样做,e,
if(prj.ProjectContents==null)
prj.ProjectContents = new ProjectContentTypeMapping();
另外,一个非常重要的事情,因为现在你的ProjectContentTypeMapping不再是一个映射表,所以,如果它的id存在于ProjectContentTypeMapping表中,删除一个Project会给你一个错误;你必须手动删除它们,即
foreach(var pctm in prj.ProjectContents.ToList())
{
prj.ProjectContents.Remove(pctm);
datacontext.ProjectContentTypeMappings.Remove(pctm);
}
datacontext.Remove(prj);
datacontext.SaveChanges();