entity-framework ef-code-first entity-framework-4.1 self-join self-reference

Entity Framework 4.1 Codifique primero Asociaciones de uno a muchos y de muchos a muchos



entity-framework ef-code-first (1)

Tengo un usuario que puede tener colección de usuarios que le gustan ...

Otro usuario puede tener una colección de usuarios que le gusten ....

Si al usuario A le gusta el usuario B y si al usuario B le gusta el usuario A, entonces pueden pasar el rato. Necesito enviarnos su información de contacto. ¿Cómo representamos este modelo en 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; } }

¿Este modelo es correcto? No puedo hacer que esto funcione.

Lo he intentado de otra manera pero eso tampoco funciona ...

Intenté agregar colección de usuario a tabla de usuario.

Por ejemplo:

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

Recibo este error cuando intento agregar usuarios y a quién les gusta:

Se detectaron cambios conflictivos en el rol ''UserLike_LikeUser_Target'' de la relación ''UserLike_LikeUser''.

¿Cuál es la mejor manera de representar tal modelo?


Realmente no necesita una entidad separada para describir la relación, el siguiente modelo de objeto hará el truco:

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

Ahora supongamos que tiene un UserId en su mano y desea encontrar al otro Usuario que le gusta este usuario y este usuario también le gusta:

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


Actualización 1:

Se asociará una asociación de muchos a muchos de autorreferencia a la base de datos utilizando una tabla de unión que requiere un modelo de objeto diferente y una API fluida por completo:

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


Actualización 2:

Como expliqué en esta publicación , una asociación de muchos a muchos no puede tener una carga útil (por ejemplo, EventId), y si ese es el caso, tenemos que dividirlo en dos asociaciones de uno a muchos para una clase interviniente y puedo vea que ha creado correctamente esta clase (UserLike) para representar la información adicional adjunta a su asociación de muchos a muchos que se auto referenciando, pero las asociaciones de esta clase intermedia no son correctas, ya que necesitamos definir exactamente 2 de muchos a uno asociación de UserLike a User como mostré en el siguiente modelo de objeto:

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

Ahora puede usar la siguiente consulta LINQ para recuperar a todos los usuarios que se gustan:

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

Espero que esto ayude.