Array
(
)

Consulta Linq para unir 2 tabelas que simula herança.

Elessandro Poças
   - 27 fev 2015

Olá a todos do fórum, estou estudando o Entity Framework 6 Code-First e estou com uma dúvida se como eu fiz está correto na questão da herança;
#Classe Pessoa
public class Pessoa
{
public int Pessoa_Id { get; set; }
public DateTime DTCadastro { get; set; }
public string NomeRazao { get; set; }
}
#Classe PessoaFisica
public class PessoaFisica : Pessoa
{
public string Cpf { get; set; }
}
#Classe PessoaJuridica
public class PessoaJuridica : Pessoa
{
public string Cnpj { get; set; }
}
#Meu contexto
public class Context : DbContext
{
public Context() : base ("MySQL")
{
}
public DbSet<Empresa> Empresas { get; set; }
public DbSet<Pessoa> Pessoas { get; set; }
public DbSet<PessoaFisica> PessoasFisicas { get; set; }
public DbSet<PessoaJuridica> PessoasJuridicas { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
#region Empresa
modelBuilder.Entity<Empresa>().ToTable("empresa")
.HasKey(e => e.Empresa_Id);
modelBuilder.Entity<Empresa>()
.Property(e => e.DTCadastro)
.HasColumnType("date");
modelBuilder.Entity<Empresa>()
.Property(e => e.Razao)
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<Empresa>()
.Property(e => e.Cnpj)
.HasMaxLength(14)
.IsRequired();
modelBuilder.Entity<Empresa>()
.Property(e => e.Ie)
.HasMaxLength(20)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.IM)
.HasMaxLength(20)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.TelFixo)
.HasMaxLength(11)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.TelCelular)
.HasMaxLength(11)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.Email)
.HasMaxLength(50)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.HomePage)
.HasMaxLength(50)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.Endereco)
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<Empresa>()
.Property(e => e.Complemento)
.HasMaxLength(50)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.Bairro)
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<Empresa>()
.Property(e => e.Cep)
.HasMaxLength(8)
.IsRequired();
modelBuilder.Entity<Empresa>()
.Property(e => e.Cidade)
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<Empresa>()
.Property(e => e.UF)
.HasMaxLength(2)
.IsRequired();
modelBuilder.Entity<Empresa>()
.Property(e => e.Apelido)
.HasMaxLength(20)
.IsRequired();
modelBuilder.Entity<Empresa>()
.Property(e => e.NumeroAtoAnatel)
.HasMaxLength(10)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.NumeroFistel)
.HasMaxLength(15)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.EngenheiroNome)
.HasMaxLength(50)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.EngenheiroTelFixo)
.HasMaxLength(11)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.EngenheiroTelCelular)
.HasMaxLength(20)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.EngenheiroEmail)
.HasMaxLength(50)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.EngenheiroNumCREA)
.HasMaxLength(20)
.IsOptional();
modelBuilder.Entity<Empresa>()
.Property(e => e.EmpresaNumCREA)
.HasMaxLength(20)
.IsOptional();
#endregion Empresa
#region Pessoa
modelBuilder.Entity<Pessoa>().ToTable("pessoa")
.HasKey(p => p.Pessoa_Id);
modelBuilder.Entity<PessoaFisica>().ToTable("pessoafisica")
.HasKey(pf => pf.Pessoa_Id);
modelBuilder.Entity<PessoaFisica>()
.Property(pf => pf.DTCadastro)
.HasColumnType("date")
.IsRequired();
modelBuilder.Entity<PessoaFisica>()
.Property(pf => pf.NomeRazao)
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<PessoaFisica>()
.Property(pf => pf.Cpf)
.HasMaxLength(11)
.IsRequired();
modelBuilder.Entity<PessoaJuridica>().ToTable("pessoajuridica")
.HasKey(pj => pj.Pessoa_Id);
modelBuilder.Entity<PessoaJuridica>()
.Property(pj => pj.DTCadastro)
.HasColumnType("date")
.IsRequired();
modelBuilder.Entity<PessoaJuridica>()
.Property(pj => pj.NomeRazao)
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<PessoaJuridica>()
.Property(pj => pj.Cnpj)
.HasMaxLength(14)
.IsRequired();

#endregion Pessoa
}
}
}
Quando eu precisar retornar os dados das duas tabelas filhas que no caso são PessoaFisica e PessoaJuridica e usei a seguinte consulta linq. A pergunta é a forma como estou fazendo está correta? Pois em uma tabela com mais de 1000 registros irei ter um bom desempenho ou tem como melhorar isto.
using (var ctx = new Context())
{
var consulta1 = (from p in ctx.Pessoas
join pf in ctx.PessoasFisicas on p.Pessoa_Id equals pf.Pessoa_Id
select new
{
Codigo = p.Pessoa_Id,
Data = p.DTCadastro,
NomeRazao = p.NomeRazao,
CpfCnpj = pf.Cpf
}).ToList();
var consulta2 = (from p in ctx.Pessoas
join pj in ctx.PessoasJuridicas on p.Pessoa_Id equals pj.Pessoa_Id
select new
{
Codigo = p.Pessoa_Id,
Data = p.DTCadastro,
NomeRazao = p.NomeRazao,
CpfCnpj = pj.Cnpj
}).ToList();
var consulta3 = consulta1.Concat(consulta2);

dataGridView1.DataSource = consulta3.ToList();
}
Exemplo de como ficou o retorno em um DataGridView (Clique na imagem para abrir em uma nova janela)

Elessandro Poças
   - 05 mar 2015

Olá a todos,
Estou postando mais uma forma que fiz para fazer a consulta.

O que está consulta está fazendo;

consulta1 = Está unindo as tabelas PessoaFisica e PessoaJuridica e retornando os dados que preciso;
consulta2 = Está fazendo um join na tabela Cliente e retornando PessoaFisica e PessoaJuridica que são clientes.

using (var ctx = new Context())
{
var consulta1 = (from pf in ctx.PessoasFisicas
select new { Codigo = pf.Pessoa_Id, Data = pf.DTCadastro, Nome = pf.NomeRazao, CpfCnpj = pf.Cpf })
.Union(from pj in ctx.PessoasJuridicas
select new { Codigo = pj.Pessoa_Id, Data = pj.DTCadastro, Nome = pj.NomeRazao, CpfCnpj = pj.Cnpj });

var consulta2 = from c in ctx.Clientes
join cli in consulta1 on c.Pessoa_Id equals cli.Codigo
orderby cli.Nome
select new
{
c.Pessoa_Id,
c.NomeRazao,
c.DTCadastro,
cli.CpfCnpj
};

dataGridView1.DataSource = consulta2.ToList();

Gostaria da opinião de vocês sobre a consulta acima, se é desta forma mesmo ou se há uma forma mais correta deste tipo de consulta.
Clique na imagem para abrir em uma nova janela