2
I’m performing a simple mapping of one-to-Many via Fluent API specifying which column is used in the mapping, however EF "ignores" the configuration and continues using the name 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:
As noted, SQL is performing a search for CodigoProjeto
and CodigoUsuario
instead of fk_projeto
and fk_usuario
Besides the exception, a doubt: I need to map this one-to-Many also in the aggregation classes (Project and User)?
If possible, I would prefer to map only the class that consumes the entity, aiming at the isolation of responsibility only for this class.
---- EDIT : Inclusion of models related to the problem ------
public class Atividade : ObjetoPersistente
{
public Atividade()
{
Projeto = new Projeto();
StatusAtividade = EStatusAtividade.NaoIniciado;
TipoAtividade = ETipoAtividade.NovaImplementacao;
Usuario = new Usuario();
}
public DateTime DataHoraFim { get; set; }
public DateTime DataHoraInicio { get; set; }
public string DescricaoAtividade { get; set; }
public string EstimativaInicialAtividade { get; set; }
public Projeto Projeto { get; set; }
public long CodigoProjeto
{
get
{
return Projeto.Codigo;
}
set
{
Projeto.Codigo = value;
}
}
public string NomeProjeto
{
get { return Projeto.Nome; }
}
public Usuario Usuario { get; set; }
public string LoginUsuario
{
get { return Usuario.Login; }
}
public long CodigoUsuario
{
get
{
if(Usuario == null) Usuario = new Usuario();
return Usuario.Codigo;
}
set
{
Usuario.Codigo = value;
}
}
public EStatusAtividade StatusAtividade { get; set; }
public string DescricaoStatusAtividade
{
get { return StatusAtividade.Descricao; }
}
public string DescricaoTipoAtividade
{
get { return TipoAtividade.Descricao; }
}
public ETipoAtividade TipoAtividade { get; set; }
public string TituloAtividade { get; set; }
public override bool Equals(object obj)
{
return (obj is Atividade) && (obj as Atividade).Codigo.Equals(Codigo);
}
public override int GetHashCode()
{
return Codigo.GetHashCode();
}
}
public class Projeto : ObjetoPersistente, IObjetoElementoOption
{
public string Nome { get; set; }
public override bool Equals(object obj)
{
return (obj is Projeto) && (obj as Projeto).Codigo.Equals(Codigo);
}
public override int GetHashCode()
{
return Codigo.GetHashCode();
}
public string Valor
{
get { return Codigo.ToString(); }
}
public string Descricao
{
get { return Nome; }
}
}
public class Usuario : ObjetoPersistente
{
public string Login { get; set; }
public string Senha { get; set; }
public override bool Equals(object obj)
{
return (obj is Usuario) && (obj as Usuario).Codigo.Equals(Codigo);
}
public override int GetHashCode()
{
return Codigo.GetHashCode();
}
}
[Serializable]
public abstract class ObjetoPersistente : IObjetoPersistente
{
public long Codigo { get; set; }
public override bool Equals(object obj)
{
return (obj is ObjetoPersistente) && (obj as ObjetoPersistente).Codigo.Equals(Codigo);
}
public override int GetHashCode()
{
return Codigo.GetHashCode();
}
/// <summary>
/// Obtêm lista de longos a partir dos códigos dos objetos persistentes.
/// </summary>
/// <param name="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 on the moment the Exception is fired ----
Exception occurs the moment I perform a find on Dbset:
_dbContext.Set<Atividade>.Find(codigoItem);
The SQL that the 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 message of the exception:
ERROR: 42703: column Extent1.CodigoProjeto does not exist
PS: I am using Postgresql.
I wanted to understand why you make a point of changing the names of the columns in the bank.
– Leonel Sanches da Silva
There is a nomenclature standard for the database, and I am working on migrating a system that is already in production with ADO.NET (pure sql).
– Joaquim Magalhães
Not use Fluent API is an option?
– Leonel Sanches da Silva
It is not feasible. Since it is a migration, it is simpler to isolate the code that has this responsibility. Unable to load templates with more annotations.
– Joaquim Magalhães
But why not use Fluent API ? It cannot solve this particularide?
– Joaquim Magalhães
You can, but you don’t solve some cases very well. I’ll think of an answer. I need Models in the body of the question.
– Leonel Sanches da Silva
Okay, they were included. Disregard the access properties, they are not being used (bridges to Project.Code, for example). Could you explain more about 'but it doesn’t solve some cases very well' ? What are the situations?
– Joaquim Magalhães
Situations of direct association, indirect association, mapping and names, finally. Your Models are quite outside the standard of the Entity Framework, so the chance of it not working is quite large. What command is used to run the query raising
Exception
?– Leonel Sanches da Silva
Well, I am making proof of concept in relation to the RU, to conclude on the feasibility or not of its use in this project. My goal is to use an ORM framework to improve. I will have models in the most diverse ways possible, with polymorphism strategies (interfaces) for example. I’m including what you asked the question.
– Joaquim Magalhães