首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在实体框架5中表达“有很多通过”的关系?

如何在实体框架5中表达“有很多通过”的关系?
EN

Stack Overflow用户
提问于 2013-10-23 19:44:19
回答 1查看 3.8K关注 0票数 3

我试图使用实体框架5查询现有的MySQL数据库。我首先使用代码创建了一个基于代码的模型,该模型映射到关于MSDN的本教程之后的现有数据库。

我有两张桌子:usersbuddiesUseridnameemailBuddy有一个user_id和一个buddy_idUser有许多Buddies (也是Users)。buddy_id列是返回到Users表的外键。因此,每个User都有许多通过Buddies实现的Users

代码语言:javascript
复制
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public IList<User> Buddies { get; set; } 
}

以下是我的数据库访问代码:

代码语言:javascript
复制
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<User>()
        };

        // 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
    }
}

此代码在上面所示的行上抛出以下异常:

System.Data.EntityCommandExecutionException:执行命令定义时发生错误。有关细节,请参阅内部异常。“

内部异常是带有以下消息的MySql.Data.MySqlClient.MySqlException

已经有一个与此连接相关联的开放DataReader,必须先关闭该连接。

我的问题:

  1. 如何创建一种关系,告诉EF每个User都有许多Buddies
  2. 一旦EF了解到User有许多Buddies,如何使用buddy_id为该Buddy找到User记录
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-24 01:37:32

您有一种数据类型,您要分别调用它们的名称。这有点让人困惑。然而,要让它首先使用代码,您只需要在自定义DbContext类中进行以下流畅的配置:

代码语言:javascript
复制
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<user>().
      HasMany(c => c.Buddies).
      WithMany().
      Map(
       m =>
       {
          m.MapLeftKey("user_id");
          m.MapRightKey("buddy_id");
          m.ToTable("buddies");
       });
}

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

代码语言:javascript
复制
[Table("user")]
public class user
{
    public int id { get; set; }
    public string name { get; set; }
    public string email { get; set; }
    public virtual List<user> Buddies { get; set; }
}

如果您使用上述方法,您所拥有的每个用户对象都将在其上具有一个名为导航属性。当查询用户时,您将希望急切地加载好友用户,请执行以下操作:

代码语言:javascript
复制
context.users.Include("Buddies")

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

代码语言:javascript
复制
var users = context.users.Include("Buddies").ToList();
foreach(var user in users)....

如果您使用上面的配置,您不需要尝试并匹配id--您只需使用好友导航属性(虚拟的、懒惰加载的)从用户那里获取好友列表(空字段,如果是新的),请执行以下操作:

代码语言:javascript
复制
user.Buddies

如您所见,您实际上并不需要“Model.buddy”(因为它只包含id映射),实体框架将负责链接。但是,如果您并不总是在用户查询中包括Buddie,那么您可能需要该表。它将以下列方式使用LINQ查询:

代码语言:javascript
复制
var userBuddies = db.buddies.Where(buddy=>buddy.user_id == user.id).ToList();
//An enumerated list of user buddies 
//do stuff
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19550923

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档