Eu sou novo no Dapper micro ORM. Até agora, posso usá-lo para coisas simples relacionadas ao ORM, mas não consigo mapear os nomes das colunas do banco de dados com as propriedades da classe.
Por exemplo, eu tenho a seguinte tabela de banco de dados:
Table Name: Person
person_id int
first_name varchar(50)
last_name varchar(50)
e eu tenho uma classe chamada Person:
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Observe que os nomes das minhas colunas na tabela são diferentes do nome da propriedade da classe para a qual estou tentando mapear os dados que obtive do resultado da consulta.
var sql = @"select top 1 PersonId,FirstName,LastName from Person";
using (var conn = ConnectionFactory.GetConnection())
{
var person = conn.Query<Person>(sql).ToList();
return person;
}
O código acima não funcionará, pois os nomes das colunas não correspondem às propriedades (Pessoa) do objeto. Nesse cenário, há algo que eu possa fazer no Dapper para mapear manualmente (por exemplo person_id => PersonId
) os nomes das colunas com propriedades do objeto?
Respostas:
Isso funciona bem:
O Dapper não possui nenhum recurso que permita especificar um Atributo de Coluna ; não sou contra a adição de suporte a ele, desde que não extraamos a dependência.
fonte
O Dapper agora suporta colunas personalizadas para mapeadores de propriedades. Isso é feito através da interface ITypeMap . Uma classe CustomPropertyTypeMap é fornecida pelo Dapper que pode executar a maior parte deste trabalho. Por exemplo:
E o modelo:
É importante observar que a implementação do CustomPropertyTypeMap exige que o atributo exista e corresponda a um dos nomes de coluna ou a propriedade não será mapeada. A classe DefaultTypeMap fornece a funcionalidade padrão e pode ser aproveitada para alterar esse comportamento:
E, com isso em prática, fica fácil criar um mapeador de tipo personalizado que usará automaticamente os atributos se estiverem presentes, mas que retornará ao comportamento padrão:
Isso significa que agora podemos suportar facilmente tipos que exigem mapa usando atributos:
Aqui está uma lista do código fonte completo .
fonte
Por algum tempo, o seguinte deve funcionar:
fonte
MatchNamesWithUnderscores
opção. Na melhor das hipóteses , se refatorássemos a API de configuração, eu deixaria oMatchNamesWithUnderscores
membro no lugar (que ainda funciona, idealmente) e adicionaria um[Obsolete]
marcador para apontar as pessoas para a nova API.Aqui está uma solução simples que não requer atributos, permitindo que você mantenha o código de infraestrutura fora dos seus POCOs.
Esta é uma classe para lidar com os mapeamentos. Um dicionário funcionaria se você mapeasse todas as colunas, mas essa classe permite especificar apenas as diferenças. Além disso, inclui mapas reversos para que você possa obter o campo da coluna e a coluna do campo, o que pode ser útil ao fazer coisas como gerar instruções sql.
Configure o objeto ColumnMap e diga ao Dapper para usar o mapeamento.
fonte
Eu faço o seguinte usando dinâmico e LINQ:
fonte
Uma maneira fácil de conseguir isso é usar aliases nas colunas da sua consulta. Se a coluna do banco de dados estiver
PERSON_ID
e a propriedade do seu objeto for,ID
você pode fazer issoselect PERSON_ID as Id ...
na sua consulta e o Dapper irá buscá-la conforme o esperado.fonte
Retirado dos testes do Dapper, atualmente no Dapper 1.42.
Classe auxiliar para obter o nome do atributo Descrição (eu pessoalmente usei a coluna como exemplo @kalebs)
Classe
fonte
GetDescriptionFromAttribute
areturn (attrib?.Description ?? member.Name).ToLower();
e acrescentou.ToLower()
quecolumnName
no mapa não deve ser maiúsculas de minúsculas.Mexer com o mapeamento é limítrofe, movendo-se para o terreno ORM real. Em vez de lutar com ele e manter o Dapper em sua verdadeira forma simples (rápida), apenas modifique seu SQL da seguinte maneira:
fonte
Antes de abrir a conexão com o banco de dados, execute este código para cada uma de suas classes poco:
Em seguida, adicione as anotações de dados às suas classes poco da seguinte maneira:
Depois disso, está tudo pronto. Basta fazer uma chamada de consulta, algo como:
fonte
Se você estiver usando o .NET 4.5.1 ou o checkout Dapper.FluentColumnMapping para mapear o estilo LINQ. Permite separar completamente o mapeamento db do seu modelo (sem necessidade de anotações)
fonte
Isso é um retrocesso de outras respostas. É apenas um pensamento que eu tinha para gerenciar as cadeias de consulta.
Person.cs
Método API
fonte
para todos que usam o Dapper 1.12, veja o que você precisa fazer para fazer isso:
e comente.
fonte
A solução de Kaleb Pederson funcionou para mim. Atualizei o ColumnAttributeTypeMapper para permitir um atributo personalizado (tinha requisito para dois mapeamentos diferentes no mesmo objeto de domínio) e atualizei as propriedades para permitir setters privados nos casos em que um campo precisava ser derivado e os tipos diferentes.
fonte
Sei que esse é um tópico relativamente antigo, mas pensei em lançar o que fiz por aí.
Eu queria que o mapeamento de atributos funcionasse globalmente. Você corresponde ao nome da propriedade (também conhecido como padrão) ou corresponde a um atributo de coluna na propriedade da classe. Eu também não queria configurar isso para todas as classes para as quais estava mapeando. Como tal, criei uma classe DapperStart que invoco no início do aplicativo:
Bem simples. Não tenho certeza de quais problemas encontrarei ainda quando acabei de escrever isso, mas funciona.
fonte
CreateChatRequestResponse
seja substituído porT
como isso iteraria em todos os objetos da Entidade. Por favor corrija-me se eu estiver errado.A solução simples para o problema que Kaleb está tentando resolver é aceitar o nome da propriedade se o atributo da coluna não existir:
fonte