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.