EF Code First – Criando chaves que não sejam Identity

Dec 22
2011

Na construção de nossas aplicações há alguns casos em que queremos que uma coluna seja chave primária de uma determinada tabela, mas, queremos que esta informação não seja gerada pelo banco de dados, ou seja, queremos que esta informação seja fornecida pelo usuário ou seja obtida de outra forma (através de um cálculo ou através de uma consulta a um sistema externo).

Para exemplificar, vamos então analisar a classe abaixo:

public class Pessoa
{
    public int CPF { get; set; }
    public string Nome { get; set; }
    public string Sobrenome { get; set; }
    public int Idade { get; set; }
}

 
Como você pode ver esta classe é bem simples, ela contêm algumas informações de cadastro de uma pessoa. A nossa intenção principal aqui é que a informação de CPF seja fornecida pelo usuário que esteja efetuando o cadastro.
 
Vamos criar então outra classe chamada PessoaConfiguration, conforme abaixo:

class PessoaConfiguration : EntityTypeConfiguration<Pessoa>
{
    public PessoaConfiguration()
    {
        HasKey(p => p.CPF);
        Property(p => p.Nome).IsRequired();
        Property(p => p.Sobrenome).IsRequired();
    }
}

 
Obs: Se você quiser aprender mais sobre o código acima, sugiro a leitura do artigo:
Data Annotations x Fluent Api
 

Esta classe faz uso da Fluent API para configurar a classe Pessoa. Sendo assim, configuramos a propriedade CPF como chave primária da tabela e informamos que a propriedade Nome e Sobrenome serão obrigatórias.
 

Mas, o que há de errado com o código acima?

 
Vamos então tentar criar um registro no banco de dados. Veja o código abaixo:

static void Main(string[] args)
{
       var pessoa = new Pessoa
       {
           Nome = "Robson",
           Sobrenome = "Ramos"
       };

       using (var context = new Context())
       {
          context.Pessoas.Add(pessoa);
          context.SaveChanges();
       }
}

 
O código acima efetua a criação de um objeto Pessoa e efetua a inserção no banco de dados. Observe que não forneci a informação de CPF (que estava configurada como obrigatória). Veja como o registro foi criado na tabela:
 

 
Apesar da propriedade CPF ser configurada como obrigatória, o banco de dados gerou um id para ela. Isto aconteceu devido ao modo de funcionamento do Entity Framework: ao encontrar um campo inteiro configurado como chave primária ele então configurará a chave primária como Identity (auto-incrementável) no banco de dados.

Para resolvermos este problema, basta efetuar a seguinte configuração na classe PessoaConfiguration. Conforme abaixo:

 

class PessoaConfiguration : EntityTypeConfiguration<Pessoa>
{
    public PessoaConfiguration()
    {
        HasKey(p => p.CPF);
        Property(p => p.CPF).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        Property(p => p.Nome).IsRequired();
        Property(p => p.Sobrenome).IsRequired();
    }
}

 
Observe sexta linha do código acima, esta instrução diz que a coluna CPF não terá seu valor gerado pelo banco de dados, ou seja, estamos sobrescrevendo a convenção do Entity Framework para que o valor seja informado no momento da inserção do registro.

Agora, precisamos alterar o código que instancia o objeto pessoa informando um número de CPF. Veja abaixo:

static void Main(string[] args)
{
            var pessoa = new Pessoa
            {
                CPF = 12345678,
                Nome = "Robson",
                Sobrenome = "Ramos"
            };

            using (var context = new Context())
            {
                context.Pessoas.Add(pessoa);
                context.SaveChanges();
            }
}

 
Agora, se olharmos na tabela podemos verificar que a informação agora foi salva com sucesso:
 

Visit Our Friends!

A few highly recommended friends...

Pages List

General info about this blog...