我该如何表达"有许多通过"在实体框架5的关系? [英] How do I express a "has many through" relationship in Entity Framework 5?

查看:148
本文介绍了我该如何表达"有许多通过"在实体框架5的关系?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用实体框架5查询现有的MySQL数据库。我使用的代码先创建一个基于代码的模型映射到一个现有的数据库以下本教程MSDN上的。



我有两个表:用户哥们。 A 用户有一个 ID ,一个名称电子邮件。 A 好友有一个 USER_ID buddy_id 。 A 用户有许多好友(也是用户) 。在 buddy_id 列是一个外键回到用户表。因此,每个用户有许多用户好友

 公共类用户
{
公众诠释标识{搞定;组; }
公共字符串名称{;组; }
公共字符串电子邮件{获得;组; }
公众的IList<使用者>鬼鬼{搞定;组; }
}

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

 使用(VAR DB =新Models.fooContext())
{
的foreach(Models.user用户db.users)
{
变种U =新用户
{
n = user.id,
名称= user.name,
=电子邮件user.email,
伙伴=新的List<使用者>()
};

//这显然是非常低效的,但我只是
//试图得到任何工作
的foreach(Models.buddy哥们db.buddies)//这一行抛出一个异常
{
如果(buddy.user_id == user.id)
{
变种b =新用户();
//采取buddy.user_id并找到该用户在用户表
u.Buddies.Add(B);
}
}

//序列化的用户,并将其写入文件在这里
}
}

这代码抛出就行了以下异常上面指出:




System.Data.EntityCommandExecutionException:执行命令定义发生了错误。详情请参阅内部异常。




内部异常是 MySql.Data.MySqlClient.MySqlException 的消息




有已与此连接,必须先关闭相关联的打开的DataReader。




我的问题:




  1. 如何创建一个关系告诉EF每个用户有许多好友

  2. 一旦EF理解一个用户有许多好友,我该如何使用 buddy_id 找到用户记录为好友


解决方案

您有您调用不同的名字一个数据类型。这是一个有点混乱,但是如果只是第一个获得此的代码工作,你需要在您的自定义的DbContext类以下流利的配置:

 保护覆盖无效OnModelCreating(DbModelBuilder模型构建器)
{
modelBuilder.Entity<使用者>()。
的hasMany(C => c.Buddies)。
WithMany()。
地图(
M = GT;
{
m.MapLeftKey(user_ID的);
m.MapRightKey(buddy_id);
M。 ToTable(死党);
});
}

这假设你的用户类看起来是这样的:

  [表(用户)] 
公共类用户
{
公众诠释ID {搞定;组; }
公共字符串名称{;组; }
公共字符串电子邮件{获得;组; }
公共虚拟列表<使用者>鬼鬼{搞定;组; }
}

如果你用上面的方法你拥有的每用户对象将有一个< STRONG>导航属性在叫鬼鬼。在查询用户,你会想要贪婪加载好友用户,这样做:

  context.users。包括(好友)

此外,为了解决与多个读者您的问题。那是因为你还没有的从你第一个循环列举查询(db.users)。要解决,你可以列举查询像这样:



  VAR用户= context.users.Include(好友)了ToList (); 
的foreach(在用户VAR用户)......



如果你使用的配置上面,你不需要尝试和匹配的id,你仅需从使用哥们的导航属性(虚,懒加载)用户好友列表(空字段是否有新的),这样​​做:

  user.Buddies 

正如你所看到的,你并不真的需要一个Model.buddy'(因为它只包含一个ID映射)
实体框架将采取联的照顾。但是,如果你并不总是包括您的用户查询好友,您可能希望表。这将与LINQ通过以下方式进行查询:

  VAR userBuddies = db.buddies.Where(哥们=>的哥们。 USER_ID == user.id).ToList(); 
//一个枚举用户的联系人名单
//做的东西


I am attempting to use Entity Framework 5 to query an existing MySQL database. I used code-first to create a code-based model that maps to an existing database following this tutorial on MSDN.

I have two tables: users and buddies. A User has an id, a name and an email. A Buddy has a user_id and a buddy_id. A User has many Buddies (which are also Users). The buddy_id column is a foreign key back into the Users table. So each User has many Users through Buddies.

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

Here is my database access code:

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

This code throws the following exception on the line indicated above:

System.Data.EntityCommandExecutionException: an error occurred while executing the command definition. See the inner exception for details."

The inner exception is a MySql.Data.MySqlClient.MySqlException with the message

There is already an open DataReader associated with this Connection which must be closed first.

My questions:

  1. How do I create a relationship that tells EF that each User has many Buddies?
  2. Once EF understands that a User has many Buddies, how do I use the buddy_id to find the User record for that Buddy?

解决方案

You have one data type that you are calling separate names. That is a little confusing. However To get this to work with code first you just need the following fluent configuration in your Custom DbContext class:

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");
       });
}

This assuming your user class looks like this:

[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; }
}

If you use the above method every user object you have will have a navigation property on it called Buddies. When querying for users you will want to eager load buddy users, do:

context.users.Include("Buddies")

Further, To address your issue with multiple readers. It is because you have not enumerated the query (db.users) from your first loop. To address that you can enumerate the query like so:

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

And if you use the configuration above, you don't need to try and match id's you simply acquire the list (null field if new) of buddies from the user using the buddies navigation property (virtual,lazy loaded), do:

user.Buddies

As you can see you don't really need a 'Model.buddy' (since it only contains an id mapping) Entity framework will take care of the linking. However if you're not always including the Buddies in your user query you may want the table. Which would be queried with LINQ in the following way:

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

这篇关于我该如何表达&QUOT;有许多通过&QUOT;在实体框架5的关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆