实体框架4.1代码首先自我引用一对多和多对多关联 [英] Entity Framework 4.1 Code First Self-Referencing One-to-Many and Many-to-Many Associations
问题描述
我有一个用户可以收集他喜欢的用户...
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屋!