根据以下帖子,我正在尝试在 Entity Framework (代码优先)中创建多对多关系:Database design for limited number of choices in MVC and Entity Framework?

但是,我无法让它正常工作,而且我确定我正在以错误的方式做一些非常简单的事情。这是我尝试中没有的图表:

联结表的要点是我需要在关系中拥有一个额外的属性 Level,所以我不能只使用顾问和程序之间的直接关系。我在设计器中手动添加了ConsultantProgramLink实体,然后分别给Program和Consultant添加关联,选择为每个添加一个FK,然后将它们设为主键。但是当我这样做时,它并没有按我预期的那样工作:

如果我在Consultant 和Program 之间建立了直接关联,我就可以在我的代码中引用Consultant.Programs。但这不适用于连接表。有什么办法可以解决这个问题,还是我总是必须通过连接属性(Consultant.ConsultantProgramLink.Programs)?无论如何,即使我确实尝试通过连接属性,它也无济于事。我可以在我的代码中执行Consultant.ConsultantProgramLink,但是另一个点不给我导航属性Programs(由于某种原因,它也变成了Program,为什么?如果最终可以访问它们,我可以重命名它们吗?) .

那么我做错了什么?为什么我不能通过我的代码中的点表示法访问属性?

最佳答案

一旦将连接表建模为实体,您确实会失去 ConsultantProgram 之间的直接多对多关系。这就是它的工作原理。您将在联结表中拥有直接的多对多关系或其他属性。不是都。如果您想要两者,您可以尝试在 Programs 上创建自定义 Consultant 属性并使用 linq 查询来获取相关程序:

public IEnumerable<Program> Programs
{
    get
    {
        return this.ConsultantProgramLinks.Select(l => l.Program);
    }
}

该示例也是对您上一个问题的解释。您不能在 Program 上拥有 ConsultantProgramLink 属性,因为它是相关实体的集合,而不是单个实体(它应该被称为 ConsultantProgramLinks )。 ConsultantProgramLink 实体中的属性简称为 Program,因为它代表单个实体而不是集合。

编辑:

如果您需要每个 Program 与每个 Consultant 自动关联,您必须在创建新的 Program 时强制执行它。将连接表作为单独的实体公开可能会让您轻松实现它:
var program = new Program();
...
context.Programs.AddObject(program);

var ids = from c in context.Consultants
          select c.Id;

foreach (var id in ids)
{
    var link = new ConsultantProgramLink
        {
            ConsultantId = id,
            Program = program
        };
    context.ConsultantProgramLinks.AddObject(link);
}

context.SaveChanges();

如果添加新的 Consultant,则必须以相同的方式创建指向所有程序的链接。

缺点是,例如,如果您有 1000 名顾问,此构造将创建 1001 个数据库插入,其中每个插入将在到数据库的单独往返中执行。为了避免它,唯一的选择是在程序表上使用存储过程或触发器。

10-04 20:36