实体框架与额外字段的多对多关系(数据库优先)

时间:2013-09-04 12:32:08

标签: c# database entity-framework ef-database-first

我有一个程序在数据访问层使用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”......

由于

1 个答案:

答案 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();