Pergunta

Como declarar um para um relacionamento usando o Entity Framework 4, o Primeiro Código (POCO)?

Eu encontrei a esta questão (um-para-um relacionamento no Entity Framework 4) , mas o artigo que a resposta referências não era útil (há uma linha de código que é uma relação de 1-1, mas nenhuma menção de como defini-lo).

Foi útil?

Solução

Você está apenas procurando algo assim?

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public Profile Profile { get; set; }
    public int ProfileId { get; set; }
}

public class Profile
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PostalCode { get; set; }
    // etc...
}

public class UserMapping : EntityConfiguration<User>
{
    public UserMapping()
    {
        this.HasKey(u => u.Id);
        this.Property(u => u.Username).HasMaxLength(32);

        // User has ONE profile.
        this.HasRequired(u => u.Profile);
    }
}

public class ProfileMapping : EntityConfiguration<Profile>
{
    public ProfileMapping()
    {
        this.HasKey(p => p.Id);
        this.Property(p => p.FirstName).HasMaxLength(32);
        this.Property(p => p.LastName).HasMaxLength(32);
        this.Property(p => p.PostalCode).HasMaxLength(6);
    }
}

EDITAR: Sim, eu não tinha vs na minha frente, mas você precisa adicionar a seguinte linha no UserMapping em vez da corrente HasRequired e também adicione um ProfileId propriedade (em vez de Profile_Id que você adicionou):

this.HasRequired(u => u.Profile).HasConstraint((u, p) => u.ProfileId == p.Id);

Atualmente, acho que não há uma maneira de contornar isso, mas tenho certeza de que isso mudará, pois estamos apenas no CTP4. Seria bom se eu pudesse dizer:

this.HasRequired(u => u.Profile).WithSingle().Map(
    new StoreForeignKeyName("ProfileId"));

Dessa forma, eu não precisaria incluir um ProfileId propriedade. Talvez exista uma maneira de contornar isso atualmente e ainda é de manhã cedo para eu pensar :).

Lembre -se também de ligar .Include("Profile") Se você deseja incluir uma "propriedade de navegação".

Outras dicas

Três métodos:

A) Declarar classes com propriedades de navegação para o outro.Marcar uma das tabelas (tabela dependente) com o ForeignKey atributo de Chave Primária.EF infere 1-a-1, a partir desta:

public class AppUser
{
    public int Id { get; set; }

    public string Username { get; set; }

    public OpenIdInfo OpenIdInfo { get; set; }
}

​public class OpenIdInfo
{
    [ForeignKey("AppUser")]
    public int Id { get; set; }

    public string OpenId { get; set; }

    public AppUser AppUser { get; set; }
}

http://weblogs.asp.net/manavi/archive/2011/05/01/associations-in-ef-4-1-code-first-part-5-one-to-one-foreign-key-associations.aspx

Eu não uso virtual e você não quer.*

B) Declarar a uma hierarquia de herança com ambos os nomes de tabela explicitamente declarado, resultando na Tabela Por Tipo e uma casa de Chave Primária.

using System.ComponentModel.DataAnnotations;

[Table("AppUser")]
public class AppUser
{
    public int Id { get; set; }

    public string Username { get; set; }

    public OpenIdInfo OpenIdInfo { get; set; }
}

[Table("AdminUser")]      
public class AdminUser : AppUser
{
    public bool SuperAdmin { get; set; }
}

Você vai ter 2 tabelas:Um para AppUser, um para AdminUser.AdminUser é de 1:1 com AppUser e é Dependente, o que significa que você pode excluir um AdminUser, mas se você excluir um AppUser quando um AdminUser ainda está apontando para ele, você vai obter um Erro de Violação de Restrição.​

C) Há 2 metade do caminho métodos de fazer um-para-um em EF:

Entidade-Divisão De, onde você tem uma Classe única, mas é armazenado em uma tabela primária, e 1 ou mais de um-para-um tabelas relacionadas.

Tabela-Divisão De, onde uma árvore de objetos nivela em uma única tabela.Por exemplo, uma classe com um Endereço de propriedade teria colunas para o Endereço do objeto, como Address_City, estruturado em uma única tabela.

*Você pode incluir virtual em qualquer EF Propriedade ou Coleções se você deseja lazy-load-los.Isso pode resultar em loops infinitos ou carregar toda a DB se você passar um objeto com preguiça propriedades carregado para, por exemplo, o MVC JSON conversor ou qualquer outra coisa que anda a hierarquia de objetos.O Lazy-Loading é sempre feito de forma Síncrona, o bloqueio de thread, e sem qualquer aviso prévio.Para resumir, a lista de maneiras que você pode congelar o seu código de aplicativo de servidor ou com ele é longo.Evite usar o virtual em aulas de EF.Sim, há um monte de exemplos de código na internet que o utilizam.Não, você ainda não deve usá-lo.

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }

    public virtual Profile Profile { get; set; }
}

public class Profile
{
    public int Id { get; set; }

    public int UserID { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PostalCode { get; set; }
}

Adicione o perfil virtual e o UserID e acho que isso deve levá -lo até lá.

Dê um exemplo das seguintes entidades aluno e estudante de aluno.
Configure um relacionamento um para zero ou um usando o DataNotações:

public class Student
{
    public Student() { }

    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }

}

public class StudentAddress 
{
    [ForeignKey("Student")]
    public int StudentAddressId { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

Quando a entidade do StudentAddress não segue convenções:

Se, por exemplo, a entidade do StudentAddress não seguir a Convenção para PK, ou seja, nome diferente para a propriedade ID, você também precisará configurá -lo para PK. Considere a seguinte entidade StudentAddress, que possui nome da propriedade, em vez de StudentAddressid.

public class Student
{
    public Student() { }

    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }

}

public class StudentAddress 
{
    [Key, ForeignKey("Student")]
    public int StudentId { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

No exemplo acima, precisamos configurar a propriedade do StudentID como chave e ForeignKey. Isso tornará a propriedade do StudentID na entidade do StudentAddress como PK e FK.

Configure um relacionamento um para zero ou um usando API fluente:
Quando estudantes e estudantes, seguem as convenções: as entidades de estudantes e estudantes seguem a convenção de código padrão para a PrimaryKey. Portanto, não precisamos configurá -los para definir seus principais tecidos. Precisamos apenas configurar a entidade do StudentAddress, onde o StudentAddressid deve ser o ForeignKey.

O exemplo a seguir define um relacionamento individual ou um relacionamento entre aluno e aluno, usando API fluente.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{

    // Configure Student & StudentAddress entity
    modelBuilder.Entity<Student>()
                .HasOptional(s => s.Address) // Mark Address property optional in Student entity
                .WithRequired(ad => ad.Student); // mark Student property as required in StudentAddress entity. Cannot save StudentAddress without Student

}

No exemplo acima, a entidade do aluno é configurada usando o método hasOptcional () que indica que a propriedade de navegação do StudentAddress na entidade do aluno é uma opção (não é necessária ao salvar a entidade do aluno). Em seguida, o método WithRequired () configura a entidade dos alunos e tornam a propriedade de navegação do aluno do StudentAddress conforme necessário (necessário ao salvar a entidade do StudentAddress. Ele lançará uma exceção quando a entidade do StudentAddress estiver economizando sem a propriedade de navegação do aluno). Isso fará com que StudentAddressid também pareça estrangeiro.

Assim, você pode configurar um relacionamento um para zero ou um entre duas entidades em que a entidade do aluno pode ser salva sem anexar o objeto StudentDress, mas a entidade do StudentAddress não pode ser salva sem anexar um objeto de entidade do aluno. Isso torna uma extremidade necessária.

Quando a entidade do StudentAddress não segue convenções:
Agora, vamos dar um exemplo de entidade do StudentAddress, onde não segue a Convenção Primária de Chave, ou seja, o nome da propriedade ID diferente do ID. Considere as seguintes entidades do aluno e dos alunos.

public class Student
{
    public Student() { }

    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }

}

public class StudentAddress 
{
    public int StudentId { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

Então, agora, precisamos configurar a propriedade do StudentID do StudentAddress para Primarykey de StudentAddress e ForeignKey, como mostrado abaixo.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure StudentId as PK for StudentAddress
    modelBuilder.Entity<StudentAddress>()
        .HasKey(e => e.StudentId);

    // Configure StudentId as FK for StudentAddress
    modelBuilder.Entity<Student>()
                .HasOptional(s => s.Address) 
                .WithRequired(ad => ad.Student); 

}

Configure um relacionamento individual usando API fluente:
Podemos configurar o relacionamento individual entre entidades usando API fluente, onde as duas extremidades são necessárias, o que significa que o objeto de entidade do aluno deve incluir o objeto de entidade do StudentAddress e a entidade do StudentAddress deve incluir o objeto da entidade do aluno para salvá-lo.

Nota: o relacionamento individual tecnicamente não é possível no MS SQL Server. Sempre será um para zero ou um. A EF forma relacionamentos individuais em entidades não em DB.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure StudentId as PK for StudentAddress
    modelBuilder.Entity<StudentAddress>()
        .HasKey(e => e.StudentId);

    // Configure StudentId as FK for StudentAddress
    modelBuilder.Entity<Student>()
                .HasRequired(s => s.Address) 
                .WithRequiredPrincipal(ad => ad.Student); 

}

No exemplo acima, o ModelBuilder.Entity (). Hasrequired (s => s.Address) faz com que a propriedade de endereço do StudentAddress seja necessária. .WithReQuiredPrincipal (ad => ad.student) torna a propriedade do aluno da entidade do StudentAddress, conforme necessário. Assim, ele configura as duas extremidades necessárias. Então, agora, quando você tenta salvar a entidade do aluno sem a entidade de endereço ou StudentAddress sem aluno, ela fará uma exceção.

Referência:http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

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