如何在Entity Framework 5中表达“有很多通过”的关系?

我试图使用Entity Framework 5来查询现有的MySQL数据库。 我使用代码优先创建一个基于代码的模型,该模型按照MSDN上的本教程映射到现有数据库。

我有两个表: usersbuddiesUseridnameemailBuddy有一个user_id和一个buddy_idUser有很多Buddies (也是Users )。 buddy_id列是返回Users表的外键。 所以每个User都有很多Users通过Buddies

 public class User { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } public IList Buddies { get; set; } } 

这是我的数据库访问代码:

 using (var db = new Models.fooContext()) { foreach (Models.user user in db.users) { var u = new User { Id = user.id, Name = user.name, Email = user.email, Buddies = new List() }; // this is obviously very inefficient but I am just // trying to get anything to work foreach (Models.buddy buddy in db.buddies) // this line throws an exception { if (buddy.user_id == user.id) { var b = new User(); // take buddy.user_id and find this user in the user table u.Buddies.Add(b); } } // serialize User and write it to a file here } } 

此代码在上面指定的行上抛出以下exception:

System.Data.EntityCommandExecutionException:执行命令定义时发生错误。 有关详细信息,请参阅内部exception。“

内部exception是带有消息的MySql.Data.MySqlClient.MySqlException

已经有一个与此Connection关联的开放DataReader,必须先关闭它。

我的问题:

  1. 如何创建一个告诉EF每个User有很多Buddies
  2. 一旦EF了解User有很多Buddies ,我如何使用buddy_id查找该BuddyUser记录?

您有一种数据类型,您正在调用单独的名称。 这有点令人困惑。 但是,要首先使用代码,您只需在Custom DbContext类中进行以下流畅配置:

 protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity(). HasMany(c => c.Buddies). WithMany(). Map( m => { m.MapLeftKey("user_id"); m.MapRightKey("buddy_id"); m.ToTable("buddies"); }); } 

假设您的用户类如下所示:

 [Table("user")] public class user { public int id { get; set; } public string name { get; set; } public string email { get; set; } public virtual List Buddies { get; set; } } 

如果你使用上面的方法,你拥有的每个用户对象都会有一个名为Buddies的导航属性 。 在查询用户时,您需要急切加载好友用户 ,请执行以下操作:

 context.users.Include("Buddies") 

此外,要解决您与多个读者的问题。 这是因为您没有枚举第一个循环中的查询 (db.users)。 要解决这个问题,您可以枚举查询,如下所示:

 var users = context.users.Include("Buddies").ToList(); foreach(var user in users).... 

如果您使用上面的配置,您不需要尝试匹配id,您只需使用伙伴导航属性 (虚拟,延迟加载)从用户获取伙伴的列表(如果是新的空字段),执行:

 user.Buddies 

正如您所看到的,您并不需要’Model.buddy’(因为它只包含一个id映射)entity framework将负责链接。 但是,如果您并不总是在用户查询中包含好友,则可能需要该表。 将通过以下方式查询LINQ:

 var userBuddies = db.buddies.Where(buddy=>buddy.user_id == user.id).ToList(); //An enumerated list of user buddies //do stuff