Inheritance with Entity Framework

2

I have a question on the inheritance part, I have the classes person and user. Person has its basic attributes and the user inherits from the person. So far so good, that's right.

My problem is that in context mapping I'm passing the user, but I do not want you to create all the person's fields in the database, so how can I limit which fields I want created in the database? or does not exist as.

Person Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;


namespace Model
{
    public class Pessoa
    {
        private int codigo;
        private int status; // Ativo = 1, Inativo = 0
        private string nome;
        private string email;
        private string cidade;
        private string endereco;
        private string bairro;
        private string numero;
        private DateTime dtCriacao;

        //Contrutor para heranca para obrigacao da criacao de usuario
        public Pessoa( string nome, string email, int status) {
            this.nome  = nome;
            this.email = email;
            this.status = status;
            this.dtCriacao = DateTime.Now;
        }

        [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
        [Required(AllowEmptyStrings = false, ErrorMessage = "Data Criaçao deve estar preenchida")]
        public DateTime DtCriacao
        {
            get { return dtCriacao; }
            set { dtCriacao = value; }
        }


        [Key]
        public int Codigo
        {
            get { return codigo; }
            set { codigo = value; }
        }

        [Required(AllowEmptyStrings = false, ErrorMessage = "Status deve estar entre 1 = Ativo ou 0 = Inativo")]
        [Range(0, 1)]
        public int Status
        {
            get { return status; }
            set { status = value; }
        }

        [StringLength(15)]
        public string Numero
        {
            get { return numero; }
            set { numero = value; }
        }

        [StringLength(80)]
        public string Bairro
        {
            get { return bairro; }
            set { bairro = value; }
        }

        [StringLength(100)]
        public string Endereco
        {
            get { return endereco; }
            set { endereco = value; }
        }

        [StringLength(100)]
        public string Cidade
        {
            get { return cidade; }
            set { cidade = value; }
        }

        [Required(AllowEmptyStrings = false, ErrorMessage = "E-mail deve estar preenchido")]
        [StringLength(250)]
        [EmailAddress(ErrorMessage = "E-mail em formato inválido.")]
        public string Email
        {
            get { return email; }
            set { email = value; }
        }

        [Required(AllowEmptyStrings = false, ErrorMessage = "Nome deve ser preenchido")]
        [StringLength(200)]
        public string Nome
        {
            get { return nome; }
            set { nome = value; }
        }


    }
}

User Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Model
{
    [Table("Usuario", Schema = "public")]
    public class Usuario : Pessoa
    {
        private string login;
        private string senha;

        public Usuario(string nome, string email, int status, string login, string senha) : base( nome, email, status)
        {
            this.login = login;
            this.senha = senha;

        }

        [Required(AllowEmptyStrings = false, ErrorMessage = "Login deve ser preenchido!")]
        [StringLength(50)]
        [Index("Ix_UsuarioLogin", IsUnique = true)]
        public string Login
        {
            get { return login; }
            set { login = value; }
        }

        [Required(AllowEmptyStrings = false, ErrorMessage = "Senha deve ser preechida!")]
        [StringLength(20)]
        public string Senha
        {
            get { return senha; }
            set { senha = value; }
        }

    }
}

Context

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Npgsql;
using System.Data.Entity;
using Model;
namespace DAL
{

        public class BaseContexto : DbContext
        {
            public BaseContexto()
                : base("Teste")
            { }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.HasDefaultSchema("public"); base.OnModelCreating(modelBuilder);
            }

            public DbSet<Usuario> Usuario { get; set; }
        }

}

My problem is here, in the table was created the address data that I do not need, type city, address, number ... How can I get this data not to be mapped?

My user table:

CREATE TABLE public."Usuario"
(
  "Codigo" integer NOT NULL DEFAULT nextval('"Usuario_Codigo_seq"'::regclass),
  "Login" character varying(50) NOT NULL DEFAULT ''::character varying,
  "Senha" character varying(20) NOT NULL DEFAULT ''::character varying,
  "DtCriacao" timestamp without time zone NOT NULL DEFAULT '-infinity'::timestamp without time zone,
  "Status" integer NOT NULL DEFAULT 0,
  "Numero" character varying(15),
  "Bairro" character varying(80),
  "Endereco" character varying(100),
  "Cidade" character varying(100),
  "Email" character varying(250) NOT NULL DEFAULT ''::character varying,
  "Nome" character varying(200) NOT NULL DEFAULT ''::character varying,
  CONSTRAINT "PK_public.Usuario" PRIMARY KEY ("Codigo")
)
WITH (
  OIDS=FALSE
);
ALTER TABLE public."Usuario"
  OWNER TO postgres;

-- Index: public."Usuario_Ix_UsuarioLogin"

-- DROP INDEX public."Usuario_Ix_UsuarioLogin";

CREATE UNIQUE INDEX "Usuario_Ix_UsuarioLogin"
  ON public."Usuario"
  USING btree
  ("Login" COLLATE pg_catalog."default");
    
asked by anonymous 06.04.2017 / 03:57

2 answers

2

First, if Usuario should not have all fields of Pessoa , then it should not inherit from person.

In your case, the most interesting approach is to make a 1-1 relationship with Usuario and Pessoa , but you would end up with the same problem you mentioned.

Your second option is to create an abstract class that serves as the basis for User and Person.

public abstract class PessoaBase
{       
    //Contrutor para heranca para obrigacao da criacao de usuario
    public PessoaBase(string nome, string email, int status) {
        this.nome  = nome;
        this.email = email;
        this.status = status;
        this.dtCriacao = DateTime.Now;
    }

    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Data Criaçao deve estar preenchida")]
    public DateTime DtCriacao { get; set; }

    [Key]
    public int Codigo { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Status deve estar entre 1 = Ativo ou 0 = Inativo")]
    [Range(0, 1)]
    public int Status { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "E-mail deve estar preenchido")]
    [StringLength(250)]
    [EmailAddress(ErrorMessage = "E-mail em formato inválido.")]
    public string Email { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Nome deve ser preenchido")]
    [StringLength(200)]
    public string Nome { get; set; }
}

[Table("Pessoa", Schema = "public")]
public class Pessoa : PessoaBase
{
    public Pessoa()
    {

    }

    [StringLength(15)]
    public string Numero { get; set; }

    [StringLength(80)]
    public string Bairro { get; set; }

    [StringLength(100)]
    public string Endereco { get; set; }

    [StringLength(100)]
    public string Cidade { get; set; }
}

[Table("Usuario", Schema = "public")]
public class Usuario : PessoaBase
{
    public Usuario()
    {

    }

    public Usuario(string nome, string email, int status, string login, string senha) : base( nome, email, status)
    {
        this.login = login;
        this.senha = senha;
    }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Login deve ser preenchido!")]
    [StringLength(50)]
    [Index("Ix_UsuarioLogin", IsUnique = true)]
    public string Login { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Senha deve ser preechida!")]
    [StringLength(20)]
    public string Senha{ get; set; }
}

Your third option is to add a metadata class to Usuario .

[Table("Pessoa", Schema = "public")]
public class Pessoa
{
    public Pessoa()
    {

    }

    //Contrutor para heranca para obrigacao da criacao de usuario
    public Pessoa(string nome, string email, int status) {
        this.nome  = nome;
        this.email = email;
        this.status = status;
        this.dtCriacao = DateTime.Now;
    }

    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Data Criaçao deve estar preenchida")]
    public DateTime DtCriacao { get; set; }

    [Key]
    public int Codigo { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Status deve estar entre 1 = Ativo ou 0 = Inativo")]
    [Range(0, 1)]
    public int Status { get; set; }

    [StringLength(15)]
    public string Numero { get; set; }

    [StringLength(80)]
    public string Bairro { get; set; }

    [StringLength(100)]
    public string Endereco { get; set; }

    [StringLength(100)]
    public string Cidade { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "E-mail deve estar preenchido")]
    [StringLength(250)]
    [EmailAddress(ErrorMessage = "E-mail em formato inválido.")]
    public string Email { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Nome deve ser preenchido")]
    [StringLength(200)]
    public string Nome { get; set; }
}

[Table("Usuario", Schema = "public")]
[MetadataType(typeof(UsuarioMetadata))]
public class Usuario : Pessoa
{
    public Usuario()
    {

    }

    public Usuario(string nome, string email, int status, string login, string senha) : base( nome, email, status)
    {
        this.login = login;
        this.senha = senha;
    }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Login deve ser preenchido!")]
    [StringLength(50)]
    [Index("Ix_UsuarioLogin", IsUnique = true)]
    public string Login { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Senha deve ser preechida!")]
    [StringLength(20)]
    public string Senha{ get; set; }
}

public class UsuarioMetadata
{
    [NotMapped]
    public string Numero { get; set; }

    [NotMapped]
    public string Bairro { get; set; }

    [NotMapped]
    public string Endereco { get; set; }

    [NotMapped]
    public string Cidade { get; set; }
}
    
06.04.2017 / 13:59
1

Another implementation alternative for your case would be to create a mapping class and use Ignore for the properties you do not want to map to the database:

Mapping class:

using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;

namespace SOpt.Entity
{
    public class UsuarioMapeamento : EntityTypeConfiguration<Usuario>
    {
        public UsuarioMapeamento()
        {
            HasKey(u => u.Codigo).Property(x => x.Codigo).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            Property(u => u.Login);
            Property(u => u.Senha);
            Property(u => u.DtCriacao);
            Property(u => u.Status);
            Property(u => u.Email);
            Property(u => u.Nome);

            Ignore(u => u.Numero);
            Ignore(u => u.Bairro);
            Ignore(u => u.Endereco);
            Ignore(u => u.Cidade);
        }
    }
}

In your context class, you must remove the line public DbSet<Usuario> Usuario { get; set; } , adding the new mapping class in the ModelBuilder settings:

using System.Data.Entity;

namespace SOpt.Entity
{
    public class BaseContexto : DbContext
    {
        public BaseContexto()
                : base("connectionstring")
        { }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.HasDefaultSchema("public");

            modelBuilder.Configurations.Add(new UsuarioMapeamento());

            base.OnModelCreating(modelBuilder);
        }
    }
}

Script generated by the entity using this implementation:

IF schema_id('public') IS NULL
    EXECUTE('CREATE SCHEMA [public]')
CREATE TABLE [public].[Usuario] (
    [Codigo] [int] NOT NULL IDENTITY,
    [Login] [nvarchar](50) NOT NULL,
    [Senha] [nvarchar](20) NOT NULL,
    [DtCriacao] [datetime] NOT NULL,
    [Status] [int] NOT NULL,
    [Email] [nvarchar](250) NOT NULL,
    [Nome] [nvarchar](200) NOT NULL,
    CONSTRAINT [PK_public.Usuario] PRIMARY KEY ([Codigo])
)
CREATE UNIQUE INDEX [Ix_UsuarioLogin] ON [public].[Usuario]([Login])
CREATE TABLE [public].[__MigrationHistory] (
    [MigrationId] [nvarchar](150) NOT NULL,
    [ContextKey] [nvarchar](300) NOT NULL,
    [Model] [varbinary](max) NOT NULL,
    [ProductVersion] [nvarchar](32) NOT NULL,
    CONSTRAINT [PK_public.__MigrationHistory] PRIMARY KEY ([MigrationId], [ContextKey])
)
INSERT [public].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'201704061249317_Inicial', N'SOpt.Entity.Migrations.Configuration',  0x1F8B0800000000000400CD58DB6EE336107D2FD07F10F4EC356307055A43DA45D64E0AA3B961E5EC6B414B639B28456A452AB0B1E897F5A19FD45FE848A2EEB66CC7BB68919768C4393C339C391CF99FBFFE763E6C436EBD42AC9814AE3D1A5ED916085F064CAC5D3BD1AB773FDB1FDEFFF883731B845BEB73B1EE3A5D879E42B9F646EB684288F2371052350C991F4B25577AE8CB90D04092F1D5D52F643422801036625996F329119A85903DE0E3540A1F229D50FE2003E0CAD8F18D97A15A8F340415511F5CDB7B8AF4F016DDF5CEB66E38A348C103BEB22D2A84D45423C1C98B024FC752ACBD080D942F7611E0BA15E50A0CF149B5FCD418AEC6690CA4722CA0FC4469199E0938BA3649216DF737A5D62E938669CBF393469DA5CEB55F544263266DABBDD764CAE3745D23B143B37C60D58C83F2F8B14AD2BF81354DB84E627005243AA67C603D274BCEFCDF60B7907F807045C2799D1732C3770D039A9E631941AC779F6065D84EB1FED64896347D49DBB9746DF9E501CD85BE1EDBD62392A04B0EE5F1D782F7B48CE1571010530DC133D51A623CBD7900A6C048EF7EF772CD44B11D161C368D6D3DD0ED3D88B5DEB8F64FD825776C0B4161300C5E04C316431F1D27B08761FFAE1E880DEDD975FC5D769DE969CCA84FCBF4CE30650B6CE2F3F963F21375EC94FA316E43CA785F0EBE4FEA1F651A6F4FE6BFC1AE0EA9BAB7DBD328959A322C58C3E8235590DA60ABF775370AA1697065366FC697837AA09B3A81A75391C8F575584AC83EB225AD4ABA49AEDD85C6930322EF3CD028C244D644DF582C2F57FCE93BEF7C450C730CE2AB3DC258B22D77421DA06B68BDCD0405EE58AC34163B5DD2F4A8A641D859D6388403092EB66AE5B92D8655DA0B87F47FD3385D856EFB57D9BBC3804294B12C362869545741C733BB6E29A7F101559D4A9E84A24FA1FB508C56D6418CE9740CA37C750C633A1DA3A663759C9AF90C3E46C91A848CED7414A3657510633A1D2317A63A446EE92238A45520ED0A249D126CDDC2ED92EE9383F69272F752165AEDEF98563C3E08767A335F625B989A5716A47DE9ED948670982E187A5FF894338CB75AF040055B81D2F9B082EA3D1AB746CAFFCF7847940AF86933DE7F3670B134B94747AA33AFDCC68C255E69EC6F68BCE7A69B8B00B6AEFD35739B58F3EDEF261F19C0C09A2BBC84BF24F86A81D7A0F5676750BB640AAB78B5E6B04B87AC0093A82F1FB2B293B964C4DA1FE01BD2569FA00E64ED18E8790352F70A3F6902EA1B8072A171ED28FBDAC16872AA970E485DE57348FD43D9998162EB0A22FD6C16E0A7D55F81166BE662258BD463707546C592D6C93C80A6586EF426D66C457D8DAF7D502A9B713F539E6425B184602E9E121D25FA46290897BCF191E490FEFDB329B0C9D9C1A1069FD4B7080169B2B4639EC4C784F1A0E47DB7A7880E40A4E562D40B59E18C8F70EB5D89F428C58940267D338840A4DAB78030E208A69E84475FE12DDC7098BF8735F577C5057618E4F84134D3EECC185DC7345406A3F24F7FFC21E9AF3FEFFF0550235FB82F120000 , N'6.1.3-40302')
    
06.04.2017 / 14:58