2011-05-12 126 views
4

我正在玩EF Code First,需要一些帮助。实体框架代码首先 - 多对多外键问题

用户可以创建许多帖子。
用户可以推荐很多文章
文章可以有很多用户推荐。

鉴于此代码:

public class User 
{ 
    public int UserID { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Post> Posts { get; set; } 
    public virtual ICollection<Post> Recommendations { get; set; } 
} 


public class Post 
{ 
    public int PostID { get; set; } 
    public int UserID { get; set; } 
    public virtual User User { get; set; } 
    public virtual ICollection<User> RecommendingUsers { get; set; } 
} 

modelBuilder.Entity<Post>() 
.HasMany(x => x.RecommendingUsers) 
.WithMany(x => x.Recommendations) 
.Map(x => x.MapLeftKey("PostID") 
    .MapRightKey("UserID") 
    .ToTable("Recommendations")); 

我结束了在Post表一个额外的 “User_UserID” 一栏,它是一个使用外键:

帖子ID(PK,INT,不空)
用户ID(INT非空)
User_UserID(FK,INT,NULL)

为什么是不是使用用户ID为t他外键?

+0

你确定。我刚刚使用了你的代码,它按预期工作。 – 2011-05-12 19:29:28

+0

我甚至尝试手动删除数据库并让EF重新创建它。我仍然以User_UserID列结束。那么,你只有你的PostID和UserID列? – Matador1006 2011-05-12 19:42:20

+0

是的。我只将所有ID重命名为Id。它的工作。 – 2011-05-12 19:45:25

回答

1

我有同样的问题,并发现两件事情:

  1. 它的使用映射列名的惯例是一样User_UserID和USER_ID,没有用户名的名字。解决方案:
    1. 您可以改变它使用的约定。我不清楚在EF 4.1中这是否可行 - Scott Gu有一篇文章感叹它不是,但是我可以看到一个Conventions属性挂在ModelBuilder类中......只有一种方法... Add( )。
    2. 您可以显式设置外键名称(见下文)。
  2. 我曾经根据StackOverflow上的建议实际修复过它,但缓存的DbModel意味着它仍然出现故障,直到我实际关闭Cassini并强制完全重新启动dev web服务器。

不幸的是,因为你不使用的命名约定的框架假设,你将不得不使用ForeignKey的所有属性在你的班,使一切一起正确配合保持,否则将保留映射到错误的列名称。

设置外键名字看起来像:

[ForeignKey("UserID")] 
public virtual User User { get; set; } 

这明确地告诉编译器使用用户名,而不是User_UserID

在许多对许多案件的框架,需要两个使用上述地图调用,并在两侧应用ForeignKey属性。

这解决了它对我来说。

我现在看到斯科特为什么要离开约定 - 当你试图将事物放在一个现有的数据库上时,这真的会烧伤。

+0

感谢您的帮助。你指出我正确的方向。我也最终不得不使用User_Id为空或者我会得到这个错误:“在表'Posts'中引入FOREIGN KEY约束'User_Posts'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。无法创建约束。“你有没有看到那种行为?你能告诉我如何使用Fluent API解决这个问题吗?我似乎无法得到正确的语法...:/ – Matador1006 2011-05-26 22:13:01