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?

StackOverflow https://stackoverflow.com//questions/9710655

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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top