7

根据以下帖子,我正在尝试在实体框架中创建多对多关系(代码优先):在 MVC 和实体框架中选择有限数量的数据库设计?

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

在此处输入图像描述

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

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

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

4

1 回答 1

11

Consultant一旦将联结表建模为实体,您确实会失去和之间的直接多对多关系Program。这就是它的工作原理。您将在联结表中具有直接的多对多关系或附加属性。不是都。如果你想要两者,你可以尝试创建自定义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 个数据库插入,其中每个插入将在单独的数据库往返中执行。为避免这种情况,唯一的选择是使用存储过程或程序表上的触发器。

于 2011-03-24T11:40:34.160 回答