First let's look at whether the derivation of Pessoa
is a composition or an inheritance. Since a Pessoa
can not be physical and legal at the same time, then it is a case of inheritance (a table represents the two entities). If it could, it would be a case of composition (a common table + 2 tables representing the data complement of each entity).
So, a good modeling would be as follows:
public class Pessoa
{
[Key]
public int PessoaId { get; set; }
[Required]
public String NomeOuRazaoSocial { get; set; }
}
public class PessoaFisica : Pessoa
{
[Required]
[Cpf] // Mais abaixo coloco a implementação desse atributo.
[Unico(ErrorMessage = "Já existe uma pessoa física com este CPF.", ModelType = typeof(PessoaFisica))] // Deste também.
public String Cpf { get; set; }
}
public class PessoaJuridica : Pessoa
{
[Required]
[Cnpj] // Mais abaixo coloco a implementação desse atributo.
[Unico(ErrorMessage = "Já existe uma pessoa jurídica com este CNPJ.", ModelType = typeof(PessoaJuridica))] // Deste também.
public String Cnpj { get; set; }
}
Here you have [Cnpj]
.
Here you have [Cpf]
.
UnicoAttribute.cs
Before implementing this attribute, install the System.Linq.Dynamic package :
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class UnicoAttribute : ValidationAttribute
{
public Type ModelType { get; set; }
public UnicoAttribute() : base() { }
public UnicoAttribute(Type _modelType) : base()
{
ModelType = _modelType;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
using (MeuContext db = new MeuContext())
{
var Name = validationContext.MemberName;
if (string.IsNullOrEmpty(Name))
{
var displayName = validationContext.DisplayName;
var prop = validationContext.ObjectInstance.GetType().GetProperty(displayName);
if (prop != null)
{
Name = prop.Name;
}
else
{
var props = validationContext.ObjectInstance.GetType().GetProperties().Where(x => x.CustomAttributes.Count(a => a.AttributeType == typeof(DisplayAttribute)) > 0).ToList();
foreach (PropertyInfo prp in props)
{
var attr = prp.CustomAttributes.FirstOrDefault(p => p.AttributeType == typeof(DisplayAttribute));
var val = attr.NamedArguments.FirstOrDefault(p => p.MemberName == "Name").TypedValue.Value;
if (val.Equals(displayName))
{
Name = prp.Name;
break;
}
}
}
}
PropertyInfo IdProp = validationContext.ObjectInstance.GetType().GetProperties().FirstOrDefault(x => x.CustomAttributes.Count(a => a.AttributeType == typeof(KeyAttribute)) > 0);
var Id = (Guid)IdProp.GetValue(validationContext.ObjectInstance, null);
Type entityType = validationContext.ObjectType;
var result = db.Set(ModelType ?? entityType).Where(Name + "==@0", value);
int count = 0;
if (Id != Guid.Empty)
{
result = result.Where(IdProp.Name + "<>@0", Id);
}
count = result.Count();
if (count == 0)
return ValidationResult.Success;
else
return new ValidationResult(ErrorMessageString);
}
}
}
To migrate the data, you can either mount an SQL script with the table already created by Migrations or make a Seed . Seed is recommended for small volumes of data. The SQL script for large volumes.
If the path is by the SQL script, be sure to fill the discriminator
column with "PersonPass" or "LegalPer."