2011-03-24 125 views
7

我试图创建实体框架(代码前)的许多一对多的关系,根据下面的帖子:Database design for limited number of choices in MVC and Entity Framework?实体框架中与联结表的多对多关系?

但是,我不能让它正常工作,我我确定我做错了一些很简单的事情。下面是图我没有从我的尝试:

enter image description here

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

如果我在顾问和程序之间做了一个直接关联,那么我就可以在我的代码中引用Consultant.Programs。但是现在对于联结表来说这不起作用。有什么办法可以解决这个问题吗?还是我总是需要通过交叉点属性(Consultant.ConsultantProgramLink.Programs)?无论如何,即使我尝试通过交叉路口属性,它也无济于事。我可以在我的代码中执行Consultant.ConsultantProgramLink,但另一个点不会给我导航属性程序(由于某种原因,它也仅仅是程序,为什么?如果我最终可以访问它们,我可以重命名它们吗?) 。

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

回答

11

将交接表建模为实体后,确实会在ConsultantProgram之间丢失直接的多对多关系。这就是它的工作原理。您将在交接表中具有直接的多对多关系或附加属性。不是都。如果你想同时你可以尝试在Consultant和使用LINQ查询创建自定义Programs属性来获取相关的程序:

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

的例子也是你的最后一个问题的解释。您不能在ConsultantProgramLink上拥有Program财产,因为它是相关实体的集合,而不是单个实体(应称为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个数据库插入,其中每个插入将在单独的数据库往返中执行。为了避免它,唯一的选择是在程序表上使用存储的程序或触发器。

+0

好的,谢谢,这是有道理的。但我想知道我是否在想这一切都是错误的?我不知道如何实际做我想要的: – Anders 2011-03-24 12:05:16

+0

说我创建一个新的顾问。我希望该顾问在其程序属性中包含所有程序。然后,我希望用户能够为每个人设定熟练程度。但1:如何将程序表中的所有程序分配给每位顾问? 2:如果我将新程序添加到程序表(我希望能够做到)怎么办?你看到我需要什么吗?程序列表,如Adobe Illustrator,MS Word等,这个列表应该是可扩展的。但是,每位顾问应该始终“拥有”其程序属性中的所有程序,并且只能在编辑配置文件时设置关卡... – Anders 2011-03-24 12:06:10

+0

我会考虑它的。 – 2011-03-24 12:47:37