Inheritance with Repository Pattern

3

I'm studying and trying to implement the Repository Pattern in C # but I'm having some difficulty solving certain inheritance problems between my Repository classes >, for example the inheritance between Pessoa , PessoaFisica and PessoaJuridica , where I created 3 classes, PessoaRepository , PessoaFisicaRepository , PessoaJuridicaRepository , where PessoaFisicaRepository and PessoaJuridicaRepository are inheriting PessoaRepository . My problem is that the PessoaRepository class is allowing you to include a Person or Person , but their respective Respository classes would have specific business rules, so the PessoaRepository class %, could not include its derivatives, remembering that I'm also trying to follow some SOLID concepts.

My classes: Template

[Table("Pessoa")]
public class PessoaEntity: IEntity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int PessoaId { get; set; }

    [Required]
    [MaxLength(100)]
    public string Nome { get; set; }

    [MaxLength(14)]
    public string CpfCnpj { get; set; }
}

[Table("PessoaFisica")]
public class PessoaFisicaEntity : PessoaEntity, IEntity
{
    public string NumeroRg { get; set; }
    public Sexo Sexo { get; set; }
}

[Table("PessoaJuridica")]
public class PessoaJuridicaEntity : PessoaEntity
{
    [MaxLength(100)]
    public string NomaFantasia { get; set; }
}

public enum Sexo
{
    Masculino = 1,
    Feminino = 2
}

public class PessoaContext : DbContext
{
    public DbSet<PessoaEntity> Pessoa { get; set; }
    public DbSet<PessoaFisicaEntity> PessoaFisica { get; set; }
    public DbSet<PessoaJuridicaEntity> PessoaJuridica { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        base.OnModelCreating(modelBuilder);
    }
}

My Repository:

    public class Repository<TEntity, TContext> : IRepository<TEntity>
    where TEntity : class, IEntity
    where TContext : DbContext, new()
{
    protected TContext _context;

    public Repository()
    {
        _context = new TContext();
    }

    public virtual TEntity Find(params object[] keyValues)
    {
        return _context.Set<TEntity>().Find(keyValues);
    }

    public virtual void InsertOrUpdate(TEntity obj)
    {
        var entity = Find(GetKeyValue(obj));
        if (entity == null)
            _context.Set<TEntity>().Add(obj);
        else
        {
            entity = obj;
        }

        _context.SaveChanges();
    }

    public virtual void Delete(params object[] keyValues)
    {
        _context.Set<TEntity>().Remove(Find(keyValues));
        _context.SaveChanges();
    }

    public virtual void Save()
    {
        _context.SaveChanges();
    }


    private object[] GetKeyValue<T>(T entity) where T : class
    {
        var properties = entity.GetType().GetProperties();
        var keysProperties = properties.Where(p => p.GetCustomAttributes(typeof(KeyAttribute), true).Length != 0);

        List<object> retorno = new List<object>();

        foreach (var key in keysProperties)
        {
            retorno.Add(key.GetValue(entity, null));
        }

        return retorno.ToArray();
    }

}

public class PessoaRepository<TPessoa> : Repository<TPessoa, PessoaContext>
    where TPessoa : PessoaEntity, IEntity
{
    public override void InsertOrUpdate(TPessoa obj)
    {
        if (ConsisteInsertOrUpdate(obj))
        {
            base.InsertOrUpdate(obj);
        }
    }

    private bool ConsisteInsertOrUpdate(PessoaEntity obj)
    {
        if (!String.IsNullOrWhiteSpace(obj.CpfCnpj))
        {
            var cpfCnpjDuplicados = _context.Pessoa.Where(a => a.CpfCnpj == obj.CpfCnpj && obj.PessoaId != a.PessoaId).Count();

            return cpfCnpjDuplicados == 0;
        }

        return true;
    }
}

public class PessoaFisicaRespository<TPessoaFisica> : PessoaRepository<TPessoaFisica>
    where TPessoaFisica: PessoaFisicaEntity, IEntity
{
    public override void InsertOrUpdate(TPessoaFisica obj)
    {
        if (ConsisteInsertOrUpdate(obj))
        {
            base.InsertOrUpdate(obj);
        }
    }

    private bool ConsisteInsertOrUpdate(PessoaFisicaEntity obj)
    {
        if (!String.IsNullOrWhiteSpace(obj.NumeroRg))
        {
            var numeroRgDuplicados = _context.PessoaFisica.Where(a => a.NumeroRg == obj.NumeroRg && obj.PessoaId != a.PessoaId).Count();

            return numeroRgDuplicados == 0;
        }

        return true;
    }
}
    
asked by anonymous 03.12.2014 / 15:30

1 answer

3

Pablo, do you intend to save this in a database? I do not know much about this pattern, but looking at how the entities were created, it seems to me a little strange.

As it is being done, you will have tables of type Pessoa , and also tables PessoaFisica and PessoaJuridica with the same fields as Pessoa .

Would not it be the case to have the 3 entities and, instead of inheritance, use an object of type Pessoa within the classes of PessoaFisica and PessoaJuridica ? It would look something like:

[Table("Pessoa")]
public class PessoaEntity: IEntity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int PessoaId { get; set; }

    [Required]
    [MaxLength(100)]
    public string Nome { get; set; }

    [MaxLength(14)]
    public string CpfCnpj { get; set; }
}

[Table("PessoaFisica")]
public class PessoaFisicaEntity : IEntity
{
    public string NumeroRg { get; set; }
    public Sexo Sexo { get; set; }

    [ForeignKey("Pessoa"), Required, Key]
    public int PessoaId { get; set; }
    public virtual PessoaEntity Pessoa { get; set; }
}

[Table("PessoaJuridica")]
public class PessoaJuridicaEntity : IEntity
{
    [MaxLength(100)]
    public string NomaFantasia { get; set; }

    [ForeignKey("Pessoa"), Required, Key]
    public int PessoaId { get; set; }
    public virtual PessoaEntity Pessoa { get; set; }
}
    
10.12.2014 / 15:26