5

我有一个在数据访问层使用实体框架(EF)数据库优先的程序。我知道,为了让 EF 自动生成多对多关系的导航属性,映射表只需要包含一个复合主键:

Project
  - ProjectId (PK)
  - Name

ContentType
  - ContentTypeId (PK)
  - Name

ProjectContentTypeMapping
  - ProjectId (PK)
  - ContentTypeId (PK)

在这种情况下,一切正常,我可以从 ContentTypes 访问项目,反之则使用导航属性。

但是,我需要具有特定于 Projects 和 ContentTypes 之间关系的额外字段,这将是 ProjectContentTypeMapping 表中的额外列。一旦我添加了这些,我就会失去导航属性,EF 在设计器中显示映射表。

有什么方法可以在 EF(数据库优先)中手动配置这两个表之间的映射?或者,我该如何表示这一点?我正在考虑可能有一个额外的“元数据”表,其中包含映射表的 FK,但对我来说它看起来很“hacky”......

谢谢

4

1 回答 1

8

不,实体框架的映射表中不能有额外的列。因为,有一个额外的列意味着你打算使用它,但映射表不是实体的一部分,所以,实体框架不再将你的带有额外列的映射表视为映射表。您将不得不手动操作映射。

让我们以您的课程为例:

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 时才这样做,即

if(prj.ProjectContents==null)
   prj.ProjectContents = new ProjectContentTypeMapping();

另外,一件非常非常重要的事情,因为现在您的 ProjectContentTypeMapping 不再是映射表,因此,如果 ProjectContentTypeMapping 表中存在其 ID,则删除项目会给您一个错误;您将不得不手动删除它们,即

foreach(var pctm in prj.ProjectContents.ToList())
{
   prj.ProjectContents.Remove(pctm);
   datacontext.ProjectContentTypeMappings.Remove(pctm);
}
datacontext.Remove(prj);
datacontext.SaveChanges();
于 2013-09-04T12:38:26.903 回答