¿Cómo definir múltiples relaciones hacia la misma tabla usando EntityFramework CodeFirst y FluentApi?

publicado por: Anonymous

Tengo un detalle con la relación de 3 tablas:

Tengo un POCO llamado ‘Domicilios’ de forma simplificada, está en la siguiente forma:

public class Domicilio
{
    public int Id { get; set; }
    public string Direccion { get; set; }
    public int? ClienteId { get; set; }
    public Cliente Cliente { get; set; }
    public int? ProveedorId { get; set; }
    public Proveedor Proveedor { get; set; }
    public int? EmpresaId { get; set; }
    public Empresa Empresa { get; set; }
}

Y tres POCOs más llamados ‘Cliente’, ‘Proveedor’ y ‘Empresa’

 public class Cliente
{
    public int Id { get; set; }
    public string Nombre { get; set; }
    public List<Domicilio> Domicilios { get; set; }
}

public class Proveedor
{
    public int Id { get; set; }
    public string Nombre { get; set; }
    public List<Domicilio> Domicilios { get; set; }
}

public class Empresa
{
    public int Id { get; set; }
    public string Nombre { get; set; }
    public Domicilio Domicilio { get; set; }
}

Proveedor y Cliente tienen muchos Domicilios, hasta ahí sin problemas. El detalle es con la relación uno a uno o uno a cero, entre Empresa y Domicilio.

Creo que la llave foránea debe ir en la tabla de domicilios apuntando al Id de la empresa mediante la propiedad EmpresaId. Pero no logro hacerlo funcionar y los registros simplemente se guardan sin relacionar en la base de datos.

Estoy usando FluentApi para la configuración de forma simplificada.
Este es el código:

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Cliente>()
            .ToTable("clientes")
            .HasMany(c => c.Domicilios)
            .WithOptional(d => d.Cliente)
            .HasForeignKey(d => d.ClienteId);

        modelBuilder.Entity<Proveedor>()
            .ToTable("proveedores")
            .HasMany(p => p.Domicilios)
            .WithOptional(d => d.Proveedor)
            .HasForeignKey(d => d.ProveedorId);

        modelBuilder.Entity<Empresa>()
            .ToTable("empresas")
            .HasOptional(e => e.Domicilio)
            .WithOptionalPrincipal(d => d.Empresa);

        modelBuilder.Entity<Domicilio>()
            .ToTable("domicilios");
    }

¿Cual es el error?

¿Es posible con EntityFramework que una tabla se comporte con HasMany para ciertas entidades y con HasOptional o HasRequired para otras?

¿Cómo defino que la llave foránea de empresa es EmpresaId en la tabla Domicilios usando FluentApi?

solución

Las relaciones de Entity framework que sean de polimofirmo se puede establecer como una herencia normal de clase:

public class Domicilio
{
  public int Id { get; set; }
public string Direccion { get; set; }
public int? ClienteId { get; set; }
public Cliente Cliente { get; set; }
public int? ProveedorId { get; set; }
public Proveedor Proveedor { get; set; }


}
    public class Empresa : Domicilio
    {

public string Nombre { get; set; }

    }

EDITADO:
Para las relaciones de herencia en EF no es necerario declar la clase hija como un dbset en el DbContext ni haría falta declarar sus relaciones. Solo iría la padre que este caso sería Domicilio:

En el Dbcontext la incluiría así

public dbset<Domicilio> Domicilio {set;get;}

Si tiene realació con otra tabla sería así:

uno a uno

modelBuilder.Entity<Domicilio>()
               .HasMany(e => e.Tabla1)
               .WithOptional(e => e.ObjectDomicilio)
               .HasForeignKey(e => e.DomicilioId);

uno a mucho

modelBuilder.Entity<Domicilio>()
                .HasMany(e => e.Tabla1)
                .WithRequired(e => e.ObjectDomicilio)//Esto es lo unico que cambia
                .HasForeignKey(e => e.DomicilioId)

En este caso no tendrias acceso directo a Empresa desde el Dbcontext pero si puedes acceder a sus datos como así:

using(var context=new Dbcontext)
{
(Empresa)context.Domicilio.where(x=>x.ClienteId==1).tolist();
}

En este caso te retornaría todos los domicilios que tienen relacion con el cliente 1 y son de tipo Empresa.

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *