Convenções do Code First

O Code First permite que você descreva um modelo usando classes C# ou Visual Basic do .NET. A forma básica do modelo é detectada usando convenções. Convenções são conjuntos de regras que são usadas para configurar automaticamente um modelo conceitual com base em definições de classe ao trabalhar com o Code First. As convenções são definidas no namespace System.Data.Entity.ModelConfiguration.Conventions.

Você pode configurar ainda mais seu modelo usando anotações de dados ou a API fluente. A precedência é dada à configuração feita por meio da API fluente seguida de anotações de dados e, por último, convenções. Para obter mais informações, consulte Anotações de dados, API Fluent – Relacionamentos, API Fluent – Tipos e Propriedades e API Fluent com VB.NET.

Uma lista detalhada das convenções do Code First está disponível na Documentação da API. Este tópico fornece uma visão geral das convenções usadas pelo Code First.

Descoberta de tipo

Ao usar o desenvolvimento do Code First, você geralmente começa escrevendo classes do .NET Framework que definem seu modelo conceitual (domínio). Além de definir as classes, você também precisa permitir que o DbContext saiba quais tipos você deseja incluir no modelo. Para fazer isso, você define uma classe de contexto que derive do DbContext e exponha as propriedades DbSet para os tipos que você deseja que façam parte do modelo. O Code First incluirá esses tipos e também extrairá qualquer tipo referenciado, mesmo se os tipos referenciados forem definidos em um assembly diferente.

Se os tipos participarem de uma hierarquia de herança, será suficiente definir uma propriedade DbSet para a classe base e os tipos derivados serão incluídos automaticamente, se estiverem no mesmo assembly que a classe base.

No exemplo a seguir, há apenas uma propriedade DbSet definida na classe SchoolEntities (Departments). O Code First usa essa propriedade para descobrir e extrair qualquer tipo referenciado.

public class SchoolEntities : DbContext
{
    public DbSet<Department> Departments { get; set; }
}

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }
    public string Name { get; set; }

    // Navigation property
    public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
    // Primary key
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }

    // Foreign key
    public int DepartmentID { get; set; }

    // Navigation properties
    public virtual Department Department { get; set; }
}

public partial class OnlineCourse : Course
{
    public string URL { get; set; }
}

public partial class OnsiteCourse : Course
{
    public string Location { get; set; }
    public string Days { get; set; }
    public System.DateTime Time { get; set; }
}

Se você quiser excluir um tipo do modelo, use o atributo NotMapped ou a API fluente DbModelBuilder.Ignore.

modelBuilder.Ignore<Department>();

Convenção da chave primária

O Code First infere que uma propriedade é uma chave primária se uma propriedade em uma classe for chamada "ID" (não diferencia maiúsculas de minúsculas) ou o nome da classe for seguido por "ID". Se o tipo da propriedade de chave primária for numérico ou GUID, ele será configurado como uma coluna de identidade.

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }

    . . .  

}

Convenção de relacionamento

No Entity Framework, as propriedades de navegação fornecem uma maneira de navegar em um relacionamento entre dois tipos de entidade. Cada objeto pode ter uma propriedade de navegação para cada relacionamento no qual participa. As propriedades de navegação permitem que você navegue e gerencie relacionamentos em ambas as direções, retornando um objeto de referência (se a multiplicidade for um ou zero ou um) ou uma coleção (se a multiplicidade for muitos). O Code First infere relacionamentos com base nas propriedades de navegação definidas nos seus tipos.

Além das propriedades de navegação, recomendamos que você inclua propriedades de chave estrangeira nos tipos que representam objetos dependentes. Qualquer propriedade com o mesmo tipo de dados que a propriedade principal da chave primária e com um nome que segue um dos seguintes formatos representa uma chave estrangeira para o relacionamento: '<nome da propriedade de navegação><nome da propriedade da chave primária principal>', '<nome da classe principal><nome da propriedade da chave principal>' ou '<nome da propriedade da chave primária principal>'. Se várias correspondências forem encontradas, a precedência será fornecida na ordem listada acima. A detecção de chave estrangeira não diferencia maiúsculas de minúsculas. Quando uma propriedade de chave estrangeira é detectada, o Code First infere a multiplicidade do relacionamento com base na nulidade da chave estrangeira. Se a propriedade for anulável, o relacionamento será registrado como opcional; caso contrário, o relacionamento será registrado como obrigatório.

Se uma chave estrangeira na entidade dependente não for anulável, o Code First definirá a exclusão em cascata no relacionamento. Se uma chave estrangeira na entidade dependente for anulável, o Code First não definirá a exclusão em cascata no relacionamento e, quando a entidade principal for excluída, a chave estrangeira será definida como nula. O comportamento de multiplicidade e da exclusão em cascata detectado por convenção pode ser substituído usando a API fluente.

No exemplo a seguir, as propriedades de navegação e uma chave estrangeira são usadas para definir o relacionamento entre as classes Department e Course.

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }
    public string Name { get; set; }

    // Navigation property
    public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
    // Primary key
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }

    // Foreign key
    public int DepartmentID { get; set; }

    // Navigation properties
    public virtual Department Department { get; set; }
}

Observação

Se você tiver várias relações entre os mesmos tipos (por exemplo, suponha que defina as classes Person e Book, em que a classe Person contém as propriedades de navegação ReviewedBooks e AuthoredBooks e a classe Book contém as propriedades de navegação Author e Reviewer ), você precisará configurar manualmente as relações usando as Anotações de Dados ou a API fluente. Para obter mais informações, consulte Anotações de dados – Relacionamentos e API fluente – Relacionamentos.

Convenção de tipos complexos

Quando o Code First descobre uma definição de classe em que uma chave primária não pode ser inferida e nenhuma chave primária é registrada por meio de anotações de dados ou da API fluente, o tipo é registrado automaticamente como um tipo complexo. A detecção de tipo complexo também exige que o tipo não tenha propriedades que referenciam tipos de entidade e não seja referenciado de uma propriedade de coleção em outro tipo. Dadas as definições de classe a seguir, o Code First inferiria que Details é um tipo complexo porque ele não tem chave primária.

public partial class OnsiteCourse : Course
{
    public OnsiteCourse()
    {
        Details = new Details();
    }

    public Details Details { get; set; }
}

public class Details
{
    public System.DateTime Time { get; set; }
    public string Location { get; set; }
    public string Days { get; set; }
}

Convenção de cadeia de conexão

Para saber mais sobre as convenções que o DbContext usa para descobrir que conexão usar, consulte Conexões e Modelos.

Removendo convenções

Você pode remover qualquer uma das convenções definidas no namespace System.Data.Entity.ModelConfiguration.Conventions. O exemplo a seguir remove PluralizingTableNameConvention.

public class SchoolEntities : DbContext
{
     . . .

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Configure Code First to ignore PluralizingTableName convention
        // If you keep this convention, the generated tables  
        // will have pluralized names.
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

Convenções personalizadas

Convenções personalizadas têm suporte a partir do EF6 em diante. Para obter mais informações, consulte Convenções personalizadas do Code First.