Fluent NxN Mapping of Classes with Compound Key

3

I have two classes that have composite primary keys, for example:

Cliente :

public class Cliente
{
    public int EscritorioId { get; set; }
    public virtual Escritorio Escritorio { get; set; }

    public int Id { get; set; }
}

public class ClienteMapping : EntityTypeConfiguration<Cliente>
{
    public ClienteMapping()
    {
        HasKey(x => new { x.Id, x.EscritorioId });
    }
}

Documento :

public class Documento
{
    public int EscritorioId { get; set; }
    public virtual Escritorio Escritorio { get; set; }

    public int Id { get; set; }

    public virtual ICollection<Cliente> ClientesComAcesso { get; set; }
}

And in the mapping of class Documento I have a NxN mapping :

public class DocumentoMapping: EntityTypeConfiguration<Documento>
{
    public DocumentoMapping()
    {
        HasKey(x => new { x.EscritorioId, x.Id });

        HasMany(x => x.Clientes)
            .WithMany()
            .Map(m => 
            {
                x.MapLeftKey("EscritorioId", "DocumentoId");
                x.MapLeftKey("EscritorioId", "ClienteId");
                x.ToTable("DocumentoClientes");
            });
    }
}

Because a customer can be a recipient / access to multiple documents.

However, when trying to generate the Migrations file for this case I get the following error:

  

The specified association foreign key columns 'DocumentId' are invalid. The number of columns specified must match the number of primary key columns.

Trying to rename composite keys such as Documento_EscritorioId and Cliente_EscritorioId , for example:

HasMany(x => x.Clientes)
    .WithMany()
    .Map(m => 
    {
        x.MapLeftKey("Documento_EscritorioId", "DocumentoId");
        x.MapLeftKey("Cliente_EscritorioId", "ClienteId");
        x.ToTable("DocumentoClientes");
    });

It works, but in this case we have a redundancy.

What is the correct way to do this mapping?

    
asked by anonymous 18.08.2015 / 21:00

1 answer

2

I do not see the need to use EntityTypeConfiguration for something so simple. Models looks like this:

public class Cliente
{
    [Key]
    public int Id { get; set; }
    public int EscritorioId { get; set; }

    public virtual Escritorio Escritorio { get; set; }
    public virtual ICollection<DocumentoCliente> DocumentosComAcesso { get; set; }
}

public class Documento
{
    public int Id { get; set; }
    public int EscritorioId { get; set; }

    public virtual Escritorio Escritorio { get; set; }    
    public virtual ICollection<DocumentoCliente> ClientesComAcesso { get; set; }
}

I think it's more interesting to create the associative entity, even if it initially seems long-winded. The gain in development is even greater, because you can put more fields inherent to the association itself:

public class DocumentoCliente 
{
    [Key]
    public int DocumentoClienteId { get; set; }
    [Index("IUQ_DocumentoCliente_DocumentoId_ClienteId", IsUnique = true, Order = 1)]
    public int DocumentoId { get; set; }
    [Index("IUQ_DocumentoCliente_DocumentoId_ClienteId", IsUnique = true, Order = 2)]
    public int ClienteId { get; set; }

    public virtual Documento Documento { get; set; }
    public virtual Cliente Cliente { get; set; }
}

[Index] , introduced in this form from the Entity Framework 6.1.0, guarantees the uniqueness of the associative register. Additional validations may be required in the application to avoid extraneous errors of key duplication for the user.

    
18.08.2015 / 21:54