Objectively speaking, through a class named ForeignKeyPropertyDiscoveryConvention
. The operation is explained here .
In roughly the way that the Entity Framework performs foreign key discovery is as follows (consider that several of these steps use # ):
It is checked in the Model if there are compatible navigation properties. For example:
public virtual EntidadeEstrangeira EntidadeEstrangeira { get; set; }
If yes, it is checked in the Model if there is any candidate property being the information component of that foreign key. For example:
public int EntidadeEstrangeiraId { get; set; }
2.1. This field may not be localized. If it is not, the Entity Framework tries to look for some property that is marked with the ForeignKeyAttribute
". This Attribute can decorate both a navigation property and a data property. For example:
[ForeignKey("EntidadeEstrangeira")]
public int OutroNomeDeEntidadeEstrangeiraQualquerId { get; set; }
or:
[ForeignKey("EntidadeEstrangeiraId")]
public virtual EntidadeEstrageira UmNomeQualquerDePropriedadeDeNavegacao { get; set; }
Furthermore, it is checked if there is any Fluent API annotation in context. There you can also configure foreign keys.
I will not go into details of the operation because it is a lot, but in general, that's it.
Your Case
I will analyze the entities one by one.
public class Predio {
public int Id { get; set; }
public string Nome { get; set; }
public Endereco Endereco { get; set; }
}
This is a classic case that falls into the first step. Normally the default is virtual
for navigation properties ( I explained this here ).
As you did not define the foreign key, if the object was not a complex type , the Entity Framework would set a foreign key for you in the table corresponding to the Model Predio
. If I'm not mistaken, I'd be Endereco_Id
.
However, you set Endereco
to a complex object. Since the ratio is 1 to 1, in the background it's as if you were defining an extension of Predio
. Notice how the schema was when generating Migration :
CreateTable(
"dbo.Predios",
c => new
{
Id = c.Int(nullable: false, identity: true),
Nome = c.String(),
Endereco_Logradouro = c.String(),
Endereco_Numero = c.String(),
Endereco_Bairro = c.String(),
Endereco_Cidade = c.String(),
Endereco_CEP = c.String(),
Construtora_Id = c.Int(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Construtoras", t => t.Construtora_Id)
.Index(t => t.Construtora_Id);
Also note that you did not set a property for Construtora_Id
, but reading Model Construtora
, which has a ratio of 1 to N with Predio
, Entity Framework has completed you would need a foreign key there, and set it to Construtora_Id
(rules 1 and 2, above).
Finally, this constructor has no use:
public Construtora()
{
this.Predios = new List<Predio>();
}
Predios
is set on the Construtora
data load automatically. You do not need to initialize it.