Alguém pode dizer o meu como posso corrigir meu modelo (Usando FluentAPI) para que eu possa atribuir um Usuário diferente para o meu Usuário.FriendCollection?
-
14-12-2019 - |
Pergunta
Eu sou novo para CodeFirst e estou tentando criar um Amigos Coleção para que dois Usuários podem ter entre si com os seus Amigos Coleção.
Aqui está a minha Classe de Usuário:
public class User
{
public User()
{
if (FriendCollection == null) FriendCollection = new Collection<Friend>();
}
public long ID { get; set; }
public virtual ICollection<Friend> FriendCollection { get; set; }
}
public class UserConfiguration : EntityTypeConfiguration<User>
{
public UserConfiguration()
{
HasKey(x => x.ID);
}
}
Aqui é o meu Amigo de Classe:
public class Friend
{
public Friend()
{
DateAdded = DateTime.UtcNow;
}
public long ID { get; set; }
public DateTime DateAdded { get; set; }
public long UserID { get; set; }
public virtual User User { get; set; }
}
public class FriendConfiguration : EntityTypeConfiguration<Friend>
{
public FriendConfiguration()
{
HasKey(x => x.ID);
HasRequired(x => x.User).WithMany(x => x.FriendCollection).HasForeignKey(x => x.UserID);
}
}
Aqui está a minha Entidade de Classe:
public Entities()
{
Database.SetInitializer<Entities>(new DropCreateDatabaseAlways<Entities>());
}
public DbSet<User> Users { get; set; }
public DbSet<Friend> Friends { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new UserConfiguration());
modelBuilder.Configurations.Add(new FriendConfiguration());
base.OnModelCreating(modelBuilder);
}
}
E aqui está o meu Código de Console e, de preferência, o que eu gostaria de alcançar:
using (Entities db = new Entities ())
{
var u1 = new User();
db.Users.Add(u1);
var u2 = new User();
db.Users.Add(u2);
u1.FriendCollection.Add(new Friend { User = u2 });
u2.FriendCollection.Add(new Friend { User = u1 });
try
{
var cnt = db.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
}
SaveChanges lança um erro sempre que eu tentava preencher o Amigo de classe com um objeto de Usuário dizendo:
A multiplicidade de restrição violada.A função 'Friend_User_Target' da relação 'Entidades.Friend_User' tem multiplicidade 1 ou 0..1.
Se eu atribuir à id de utilizador como este:
u1.FriendCollection.Adicionar(novo Amigo { UserID = u2.ID });
Isto permite-me para guardar as entidades, mas não corretamente!
Quando eu passo através do código que eu possa isolar o problema e aqui está o que eu acho:
b.FriendCollection.Add(new Friend { UserID = a.ID });
//Friend.UserID = 1
db.SaveChanges();
//Friend.UserID = 2 matching the b.ID
Então, agora eu posso voltar para o meu exemplo anterior e SaveChanges() sem gerar o erro se eu atribuir a um Amigo.Usuário o Usuário chamado.Por exemplo:
b.FriendCollection.Add(new Friend { User = b });
db.SaveChanges()
Mas quando tentar atribuir um usuário diferente recebo a mensagem de erro.Por exemplo:
b.FriendCollection.Add(new Friend { User = a });
db.SaveChanges()
Eu recebo:
A multiplicidade de restrição violada.A função 'Friend_User_Target' da relação 'Entidades.Friend_User' tem multiplicidade 1 ou 0..1.
Alguém pode dizer o meu como posso corrigir meu modelo (Usando FluentAPI) para que eu possa atribuir um Usuário diferente para o meu Usuário.FriendCollection?
Solução
O mapeamento não é correto, pelo menos não correta para o significado das relações em seu modelo.
O mapeamento cria um relacionamento e as duas propriedades de navegação User.FriendCollection
e Friend.User
são as duas extremidades de uma única relação.Você definidos como o inverso propriedades.
Mas isso significa que se você tiver um usuário Utilizadora, que tem um FriendB no FriendCollection
o User
em FriendB deve ser Utilizadora e não qualquer outro usuário.O modelo só pode expressar que um usuário é um amigo de si próprio/a, por assim dizer.Porque você está adicionando outro usuário para a coleção que você obtenha exceções.
Na minha opinião, a entidade Friend
não representam um amigo = outro usuário, mas, na verdade, expressa um relacionamento.É uma espécie de entidade intermediária para um muitos-para-muitos de relacionamento entre os usuários e essa relação é Friendship
(Eu prefiro chamá-lo desta forma.)
Em qualquer caso, o modelo precisa de duas relações.Você pode deixar a entidades como eles são, mas usar esse mapeamento:
public class UserConfiguration : EntityTypeConfiguration<User>
{
public UserConfiguration()
{
HasKey(x => x.ID);
HasMany(x => x.FriendCollection)
.WithRequired();
}
}
public class FriendConfiguration : EntityTypeConfiguration<Friend>
{
public FriendConfiguration()
{
HasKey(x => x.ID);
HasRequired(x => x.User)
.WithMany()
.HasForeignKey(x => x.UserID)
.WillCascadeOnDelete(false);
}
}
(Desabilitar a exclusão em cascata em uma das relações é necessário para evitar o infame "vários exclusão em cascata caminho de exceção".)
Note que você tem agora duas chaves estrangeiras no Friend
tabela UserID
para o segundo e User_ID
para o primeiro mapeamento.Você pode renomear o nome padrão da coluna adicionando Map(m => m.MapKey("SomeUserID"))
para o primeiro mapeamento.
Com este mapeamento seu console de código deve funcionar.