One-To-Many relationship with explicit foreign key name

2

I'm performing a simple one-to-many mapping via Fluent API specifying which column is used in the mapping, but EF "ignores" the configuration and continues using the default .

Mappings:

        public AtividadeMap()
        {
            HasKey(a => a.Codigo);

            ToTable("tb_atividade");

            Property(a => a.TituloAtividade).HasColumnName("titulo_atividade");
            Property(a => a.DescricaoAtividade).HasColumnName("descricao_atividade");
            Property(a => a.DataHoraInicio).HasColumnName("data_hora_inicio");
            Property(a => a.DataHoraFim).HasColumnName("data_hora_fim");
            Property(a => a.Codigo).HasColumnName("pk_atividade");
            Property(a => a.StatusAtividade.Identificador).HasColumnName("status_atividade");
            Property(a => a.EstimativaInicialAtividade).HasColumnName("estimativa_inicial_atividade");
            Property(a => a.TipoAtividade.Identificador).HasColumnName("tipo_atividade");

            HasRequired(a => a.Usuario)
           .WithMany()
           .Map(e => e.MapKey("fk_usuario"));

            HasRequired(a => a.Projeto)
           .WithMany()
           .Map(e => e.MapKey("fk_projeto"));

        }


        public ProjetoMap()
        {
            HasKey(a => a.Codigo);

            ToTable("tb_projeto");

            Property(p => p.Codigo).HasColumnName("pk_projeto");
            Property(a => a.Nome).HasColumnName("nome");
        }

Exception:

Asnoted,SQLissearchingforCodigoProjetoandCodigoUsuarioinsteadoffk_projetoandfk_usuario

Inadditiontotheexception,onequestion:DoIneedtomapthisone-to-manyclassalsoinaggregation(ProjectandUser)?

Ifpossible,Iwouldprefertomaponlytheclassthatconsumestheentity,aimingtoisolatetheresponsibilityonlyforthisclass.

----EDIT:Inclusionofmodelsrelatedtotheproblem------

publicclassAtividade:ObjetoPersistente{publicAtividade(){Projeto=newProjeto();StatusAtividade=EStatusAtividade.NaoIniciado;TipoAtividade=ETipoAtividade.NovaImplementacao;Usuario=newUsuario();}publicDateTimeDataHoraFim{get;set;}publicDateTimeDataHoraInicio{get;set;}publicstringDescricaoAtividade{get;set;}publicstringEstimativaInicialAtividade{get;set;}publicProjetoProjeto{get;set;}publiclongCodigoProjeto{get{returnProjeto.Codigo;}set{Projeto.Codigo=value;}}publicstringNomeProjeto{get{returnProjeto.Nome;}}publicUsuarioUsuario{get;set;}publicstringLoginUsuario{get{returnUsuario.Login;}}publiclongCodigoUsuario{get{if(Usuario==null)Usuario=newUsuario();returnUsuario.Codigo;}set{Usuario.Codigo=value;}}publicEStatusAtividadeStatusAtividade{get;set;}publicstringDescricaoStatusAtividade{get{returnStatusAtividade.Descricao;}}publicstringDescricaoTipoAtividade{get{returnTipoAtividade.Descricao;}}publicETipoAtividadeTipoAtividade{get;set;}publicstringTituloAtividade{get;set;}publicoverrideboolEquals(objectobj){return(objisAtividade)&&(objasAtividade).Codigo.Equals(Codigo);}publicoverrideintGetHashCode(){returnCodigo.GetHashCode();}}publicclassProjeto:ObjetoPersistente,IObjetoElementoOption{publicstringNome{get;set;}publicoverrideboolEquals(objectobj){return(objisProjeto)&&(objasProjeto).Codigo.Equals(Codigo);}publicoverrideintGetHashCode(){returnCodigo.GetHashCode();}publicstringValor{get{returnCodigo.ToString();}}publicstringDescricao{get{returnNome;}}}publicclassUsuario:ObjetoPersistente{publicstringLogin{get;set;}publicstringSenha{get;set;}publicoverrideboolEquals(objectobj){return(objisUsuario)&&(objasUsuario).Codigo.Equals(Codigo);}publicoverrideintGetHashCode(){returnCodigo.GetHashCode();}}[Serializable]publicabstractclassObjetoPersistente:IObjetoPersistente{publiclongCodigo{get;set;}publicoverrideboolEquals(objectobj){return(objisObjetoPersistente)&&(objasObjetoPersistente).Codigo.Equals(Codigo);}publicoverrideintGetHashCode(){returnCodigo.GetHashCode();}///<summary>///Obtêmlistadelongosapartirdoscódigosdosobjetospersistentes.///</summary>///<paramname="lista"></param>
        /// <returns></returns>
        public static List<long> ObtenhaListaDeCodigosPorListaDeObjetos<T>(List<T> lista) where T:ObjetoPersistente
        {
            var listaLongo = new List<long>();

            foreach (var objetoPersistente in lista)
            {
                listaLongo.Add(objetoPersistente.Codigo);
            }

            return listaLongo;
        }

        /// <summary>
        /// Obtêm lista de objetos do tipo genérico a partir de lista de códigos
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listaDeCodigos"></param>
        /// <returns></returns>
        public static List<T> ObtenhaListaDeObjetoPorListaDeCodigos<T>(List<long> listaDeCodigos) where T  : ObjetoPersistente
        {
            var listaObjeto = new List<T>();

            foreach (var codigo in listaDeCodigos)
            {
                var objeto = Activator.CreateInstance<T>();
                objeto.Codigo = codigo;

                listaObjeto.Add(objeto);
            }

            return listaObjeto;
        }

        /// <summary>
        /// Obtêm objetos persistentes da lista que possuem a propriedade Código equivalente a 0.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objetos"></param>
        /// <returns></returns>
        public static List<T> ObtenhaObjetosComCodigoZerado<T>(List<T> objetos) where T : ObjetoPersistente
        {
            var resultado = new List<T>();

            foreach (var objeto in objetos)
            {
                if(objeto.Codigo.Equals(0))
                    resultado.Add(objeto);
            }

            return resultado;
        }

        /// <summary>
        /// Obtêm objetos persistentes da lista que possuem a propriedade Código diferente de 0.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objetos"></param>
        /// <returns></returns>
        public static List<T> ObtenhaObjetosComCodigoDiferenteDeZero<T>(List<T> objetos) where T : ObjetoPersistente
        {
            var resultado = new List<T>();

            foreach (var objeto in objetos)
            {
                if (!objeto.Codigo.Equals(0))
                    resultado.Add(objeto);
            }

            return resultado;
        }

        /// <summary>
        /// Compara duas listas de objetos persistentes
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listaBase"></param>
        /// <param name="listaAnalisada"></param>
        /// <returns>Os objetos persistentes da 'listaAnalisada' que não existem na 'listaBase'</returns>
        public static List<T> ObtenhaDiferenteEntreListas<T>(List<T> listaBase, List<T> listaAnalisada)
            where T : ObjetoPersistente
        {
            var resultado = new List<T>();

            foreach (var objetoPersistente in listaAnalisada)
            {
                if(!listaBase.Contains(objetoPersistente))
                    resultado.Add(objetoPersistente);
            }

            return resultado;
        }
    }

---- EDIT2: Details about when the exception is thrown ----

The exception occurs when I perform a 'find' in DbSet:

_dbContext.Set<Atividade>.Find(codigoItem);

The SQL that EF produced was this:

SELECT "Alias1"."status_atividade", "Alias1"."pk_atividade", "Alias1"."data_hora_fim", "Alias1"."data_hora_inicio", "Alias1"."descricao_atividade", "Alias1"."estimativa_inicial_atividade", "Alias1"."CodigoProjeto", "Alias1"."CodigoUsuario", "Alias1"."tipo_atividade", "Alias1"."titulo_atividade", "Alias1"."fk_projeto", "Alias1"."fk_usuario" FROM (SELECT "Extent1"."pk_atividade", "Extent1"."data_hora_fim", "Extent1"."data_hora_inicio", "Extent1"."descricao_atividade", "Extent1"."estimativa_inicial_atividade", "Extent1"."CodigoProjeto", "Extent1"."CodigoUsuario", "Extent1"."status_atividade", "Extent1"."tipo_atividade", "Extent1"."titulo_atividade", "Extent1"."fk_projeto", "Extent1"."fk_usuario" FROM "public"."tb_atividade" AS "Extent1" WHERE "Extent1"."pk_atividade" = ((4)) LIMIT 2) AS "Alias1"

The exception message:

ERROR: 42703: column Extent1.CodigoProjeto does not exist

PS: I'm using PostgreSQL.

    
asked by anonymous 16.07.2015 / 20:33

1 answer

1

Let's start with the generated SQL:

SELECT "Alias1"."status_atividade", "Alias1"."pk_atividade",
"Alias1"."data_hora_fim", "Alias1"."data_hora_inicio",
"Alias1"."descricao_atividade", "Alias1"."estimativa_inicial_atividade",
"Alias1"."CodigoProjeto", "Alias1"."CodigoUsuario",
"Alias1"."tipo_atividade", "Alias1"."titulo_atividade",
"Alias1"."fk_projeto", "Alias1"."fk_usuario" FROM 
    (SELECT "Extent1"."pk_atividade", "Extent1"."data_hora_fim",
    "Extent1"."data_hora_inicio", "Extent1"."descricao_atividade",
    "Extent1"."estimativa_inicial_atividade", "Extent1"."CodigoProjeto", 
    "Extent1"."CodigoUsuario", "Extent1"."status_atividade",
    "Extent1"."tipo_atividade", "Extent1"."titulo_atividade",
    "Extent1"."fk_projeto", "Extent1"."fk_usuario" 
    FROM "public"."tb_atividade" AS "Extent1" 
    WHERE "Extent1"."pk_atividade" = ((4)) LIMIT 2) AS "Alias1"

Please note that at no time do you reference CodigoProjeto and CodigoUsuario here:

    public AtividadeMap()
    {
        HasKey(a => a.Codigo);

        ToTable("tb_atividade");

        Property(a => a.TituloAtividade).HasColumnName("titulo_atividade");
        Property(a => a.DescricaoAtividade).HasColumnName("descricao_atividade");
        Property(a => a.DataHoraInicio).HasColumnName("data_hora_inicio");
        Property(a => a.DataHoraFim).HasColumnName("data_hora_fim");
        Property(a => a.Codigo).HasColumnName("pk_atividade");
        Property(a => a.StatusAtividade.Identificador).HasColumnName("status_atividade");
        Property(a => a.EstimativaInicialAtividade).HasColumnName("estimativa_inicial_atividade");
        Property(a => a.TipoAtividade.Identificador).HasColumnName("tipo_atividade");

        HasRequired(a => a.Usuario)
       .WithMany()
       .Map(e => e.MapKey("fk_usuario"));

        HasRequired(a => a.Projeto)
       .WithMany()
       .Map(e => e.MapKey("fk_projeto"));

    }

Obviously it will not work. Because the two properties are not part of the query (because they are not data fields, but navigation properties that you have defined yourself), you need to mark these properties with [NotMapped] to remove the query columns.

    [NotMapped]
    public long CodigoProjeto {
        get
        {
            return Projeto.Codigo;
        }
        set
        {
            Projeto.Codigo = value;
        }
    }

    [NotMapped]
    public long CodigoUsuario {
        get
        {
            if(Usuario == null) Usuario = new Usuario();
            return Usuario.Codigo;
        }
        set
        {
            Usuario.Codigo = value;
        }
    }
    
16.07.2015 / 23:22