Problem with ValueObject in the Entity framework

3

I'm having a difficulty with a mapping and would like to know if it's possible to do this:

I have a Contact class with two fields that are ValueObject of type "Phone", the fields are Phone and Cell.

public Telefone Telefone { get; set; }
public Telefone Celular { get; set; }

I would like to do the following mapping, so that Phone is mandatory and the cell phone is not:

Property(x => x.Telefone.DDD)
  .HasColumnName("TelefoneDDD")
  .IsRequired();
Property(x => x.Telefone.Numero)
  .HasColumnName("Telefone")
  .IsRequired();
Property(x => x.Celular.DDD)
  .HasColumnName("CelularDDD")
  .IsOptional();
Property(x => x.Celular.Numero)
  .HasColumnName("Celular")
  .IsOptional();

When I generate the migration, I get the following error:

  

Conflicting configuration settings were specified for property 'Number' on type 'System.Domain.ValueObject.Telephone':   IsNullable = False conflicts with IsNullable = True

    
asked by anonymous 06.04.2016 / 18:41

2 answers

0

You should have a separate configuration for the Phone entity and just make the key for the two fields in your parent entity. In one of them you leave as Required and the other does not

public class Telefone
{
    public int Codigo {get;set;}
    public int DDD {get;set;}
    public string Numero {get;set;}
}

public class Cadastro
{
    public int CodigoTelefone {get;set;}
    public Telefone Telefone {get;set;}
    public int? CodigoCelular {get;set;}
    public Telefone Celular {get;set;}
}

//Mapeamento da classe Cadastro

HasRequired(c => c.Telefone)
    .WithMany()
    .HasForeignKey(c => c.CodigoTelefone)
    .WillCascadeOnDelete(true); // Telefone é obrigatório

HasOptional(c => c.Celular)
    .WithMany()
    .HasForeignKey(c => c.CodigoCelular)
    .WillCascadeOnDelete(true); // Celular não é obrigatório
    
06.04.2016 / 18:57
0

The solution to this problem really is not elegant. According to this question opened in the Github of the Entity Framework there is a limitation on how it maps the entities in its conceptual model (C-Space).

Note: The answer in Github is later than this question and so I found it interesting to post here.

The solution I have used is very similar to what gabriel.santos suggested: create value objects (VO) that are subclasses of other VOs and configure only the subclasses according to the need of each entity. Ex.:

// classes
public class Telefone { /*...* /} 
public class TelefoneFixo : Telefone { /**/ }
public class TelefoneCelular : Telefone  { /**/ }

// propriedades de Contato
public TelefoneFixo Telefone { get; set; }
public TelefoneCelular Celular { get; set; }

// a configuração da entidade permanece inalterada

[Addendum] There are other issues around the mapping of entities that use complex types such as VO: it is not possible to use properties of a complex type in primary keys, in relationship composition (FK), or as a parameter to the AddOrUpdate method. >     

04.10.2017 / 15:28