实体框架4.1代码首先自我引用一对多和多对多关联 [英] Entity Framework 4.1 Code First Self-Referencing One-to-Many and Many-to-Many Associations

查看:129
本文介绍了实体框架4.1代码首先自我引用一对多和多对多关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用户可以收集他喜欢的用户...

I have a User that can have collection of users he likes...

另一个用户可以拥有他喜欢的用户的集合。

Another user can have collection of users he likes....

如果用户A喜欢用户B,如果用户B喜欢用户A,则可以挂起。我需要发送他们的联系方式。我们如何在实体框架代码中代表这样一个模型?

If User A likes User B and if User B likes User A, then they get to hang out. I need to send each other their contact info. How do we represent such a model in Entity Framework Code First?

public class User
{
    public int UserId { get; set; }

    public int? UserLikeId { get; set; }
    public virtual UserLike UserLike { get; set; }
}

public class UserLike
{
    public int UserLikeId { get; set; }

    public int UserId { get; set; }
    public virtual User User { get; set; }

    public virtual ICollection<User> LikeUsers { get; set; }
}

这个模型是否正确?我不能让这个工作。

Is this model correct? I can't get this to work.

我尝试过另一种方式,但也不行。

I've tried another way but that doesn't work too...

我试图添加

例如:

public virtual ICollection<User> userlike { get; set; }

public class User
{
    public int UserId { get; set; }
    public virtual ICollection<UserLike> UserLikes { get; set; }
}

public class UserLike
{
    public int UserLikeId { get; set; }

    public int UserId { get; set; }
    public virtual User User { get; set; }

    public int LikeUserId { get; set; }
    public virtual User LikeUser { get; set; }
}

当我尝试添加用户和他们喜欢的人时,我收到此错误:

I get this error when I try to add user and who they like:


已检测到与UserLike_LikeUser关系的角色UserLike_LikeUser_Target发生冲突的更改。

Conflicting changes to the role 'UserLike_LikeUser_Target' of the relationship 'UserLike_LikeUser' have been detected.

代表这样一个模型的最好方法是什么?

What's the best way to represent such a model?

推荐答案

真的需要一个单独的实体来描述这种关系,下面的对象模型将会诀窍:

You don't really need a separate entity to describe the relationship, the object model below will do the trick:

public class User
{
    public int UserId { get; set; }
    public string Name { get; set; }

    public int? ThisUserLikesId { get; set; }
    public virtual User ThisUserLikes { get; set; }
    public virtual ICollection<User> LikeThisUser { get; set; }
}

public class Context : DbContext
{
    public DbSet<User> Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
                    .HasOptional(u => u.ThisUserLikes)
                    .WithMany(u => u.LikeThisUser)
                    .HasForeignKey(u => u.ThisUserLikesId);
    }
}

现在我们假设你手中有一个UserId想找到其他喜欢该用户的用户也喜欢他的用户:

Now let's say you have a UserId in your hand and want to find the other User who likes this user which this user also like him:

using (var context = new Context())
{
    // For a given user id = 1
    var friends = (from u in context.Users
                   where u.UserId == 1
                   from v in u.LikeThisUser
                   where v.UserId == u.ThisUserLikesId
                   select new 
                   { 
                       OurUser = u, 
                       HerFriend = v 
                   })
                   .SingleOrDefault();

    ExchangeContactInfo(friends.OurUser, friends.HerFriend);
}                


自引用多对多关联将使用连接表映射到数据库,该连接表需要不同的对象模型和流畅的API: / p>

A self referencing many-to-many association will be mapped to database using a join table which require a different object model and fluent API altogether:

public class User
{
    public int UserId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<User> ThisUserLikes { get; set; }
    public virtual ICollection<User> UsersLikeThisUser { get; set; }
}

public class Context : DbContext
{
    public DbSet<User> Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
                    .HasMany(u => u.ThisUserLikes)
                    .WithMany(u => u.UsersLikeThisUser)
                    .Map(c => 
                    {
                        c.MapLeftKey("UserId");
                        c.MapRightKey("OtherUserId");
                        c.ToTable("UserLikes");
                    });
    }
}


正如我在这篇文章,一个多对多关联不能有一个有效负载(例如EventId),如果是这种情况,那么我们必须把它分解成两个一对多关联到一个中间类,我可以看到你已经正确地创建了这个类(UserLike)来表示额外的信息附加到您的自引用多对多关联,但这个中间类的关联是不正确的,因为我们需要定义从UserLike到用户的两个一对一的关联,就像我在以下对象模型中显示的:

As I explained in this post, a many-to-many association cannot have a payload (e.g EventId), and if that’s the case then we have to break it down to two one-to-many associations to an intervening class and I can see you’ve correctly created this class (UserLike) to represent the extra information attached to your self-referencing many-to-many association but the associations from this intermediate class are not correct as we need to define exactly 2 many-to-one association from UserLike to User like I showed in the following object model:

public class User
{        
    public int UserId { get; set; }
    public string Email { get; set; }       

    public virtual ICollection ThisUserLikes { get; set; }
    public virtual ICollection UsersLikeThisUser { get; set; }
}       

public class UserLike
{
    public int UserLikeId { get; set; }
    public int LikerId { get; set; }
    public int LikeeId { get; set; }
    public int EventId { get; set; }

    public User Liker { get; set; }
    public User Likee { get; set; }
    public virtual Event Event { get; set; }
}

public class Event
{
    public int EventId { get; set; }
    public string Name { get; set; }
}  

public class Context : DbContext 
{
    public DbSet Users { get; set; } 
    public DbSet Events { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity()
                    .HasMany(u => u.ThisUserLikes)
                    .WithRequired(ul => ul.Liker)
                    .HasForeignKey(ul => ul.LikerId);
        modelBuilder.Entity()                        
                    .HasMany(u => u.UsersLikeThisUser)
                    .WithRequired(ul => ul.Likee)
                    .HasForeignKey(ul => ul.LikeeId)
                    .WillCascadeOnDelete(false);
    }
}

现在您可以使用以下LINQ查询检索所有喜欢彼此的用户:

Now you can use the following LINQ query to retrieve all the users who like each other:

using (var context = new Context())
{                
    var friends = (from u1 in context.Users
                   from likers in u1.UsersLikeThisUser
                   from u2 in u1.ThisUserLikes 
                   where u2.LikeeId == likers.LikerId
                   select new
                   {
                       OurUser = u1.UserId,
                       HerFriend = u2.LikeeId 
                   })
                   .ToList();
}

希望这有帮助。

这篇关于实体框架4.1代码首先自我引用一对多和多对多关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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