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;
}
}