Soy nuevo en Dapper micro ORM. Hasta ahora, puedo usarlo para cosas simples relacionadas con ORM, pero no puedo asignar los nombres de columna de la base de datos con las propiedades de la clase.
Por ejemplo, tengo la siguiente tabla de base de datos:
Table Name: Person
person_id int
first_name varchar(50)
last_name varchar(50)
y tengo una clase llamada Persona:
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Tenga en cuenta que los nombres de mis columnas en la tabla son diferentes del nombre de la propiedad de la clase a la que estoy tratando de asignar los datos que obtuve del resultado de la 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;
}
El código anterior no funcionará ya que los nombres de las columnas no coinciden con las propiedades del objeto (Persona). En este escenario, ¿hay algo que pueda hacer en Dapper para asignar manualmente (por ejemplo person_id => PersonId
) los nombres de columna con propiedades de objeto?
Respuestas:
Esto funciona bien:
Dapper no tiene ninguna facilidad que le permita especificar un Atributo de columna , no estoy en contra de agregarle soporte, siempre que no obtengamos la dependencia.
fuente
Dapper ahora admite columnas personalizadas para mapeadores de propiedades. Lo hace a través de la interfaz ITypeMap . Dapper proporciona una clase CustomPropertyTypeMap que puede hacer la mayor parte de este trabajo. Por ejemplo:
Y el modelo:
Es importante tener en cuenta que la implementación de CustomPropertyTypeMap requiere que el atributo exista y coincida con uno de los nombres de columna o la propiedad no se asignará. La clase DefaultTypeMap proporciona la funcionalidad estándar y se puede aprovechar para cambiar este comportamiento:
Y con eso en su lugar, se vuelve fácil crear un mapeador de tipos personalizado que usará automáticamente los atributos si están presentes, pero de lo contrario volverá al comportamiento estándar:
Eso significa que ahora podemos admitir fácilmente los tipos que requieren un mapa usando atributos:
Aquí hay un resumen del código fuente completo .
fuente
Por algún tiempo, lo siguiente debería funcionar:
fuente
MatchNamesWithUnderscores
opción. En el mejor de los casos , si refactorizamos la API de configuración, dejaría alMatchNamesWithUnderscores
miembro en su lugar (que todavía funciona, idealmente) y agregaría un[Obsolete]
marcador para señalar a las personas a la nueva API.Aquí hay una solución simple que no requiere atributos que le permitan mantener el código de infraestructura fuera de sus POCO.
Esta es una clase para tratar con las asignaciones. Un diccionario funcionaría si asignara todas las columnas, pero esta clase le permite especificar solo las diferencias. Además, incluye mapas inversos para que pueda obtener el campo de la columna y la columna del campo, lo que puede ser útil al hacer cosas como generar sentencias sql.
Configure el objeto ColumnMap y dígale a Dapper que use la asignación.
fuente
Hago lo siguiente usando dynamic y LINQ:
fuente
Una manera fácil de lograr esto es usar solo alias en las columnas de su consulta. Si la columna de su base de datos es
PERSON_ID
y la propiedad de su objeto es loID
que puede hacerselect PERSON_ID as Id ...
en su consulta y Dapper lo recogerá como se esperaba.fuente
Tomado de las pruebas Dapper que actualmente se encuentra en Dapper 1.42.
Clase auxiliar para obtener el nombre del atributo Descripción (personalmente he usado Columna como ejemplo @kalebs)
Clase
fuente
GetDescriptionFromAttribute
areturn (attrib?.Description ?? member.Name).ToLower();
y añadió.ToLower()
quecolumnName
en el mapa no debería ser entre mayúsculas y minúsculas.Jugar con el mapeo es moverse al límite en tierra ORM real. En lugar de luchar con él y mantener a Dapper en su verdadera forma simple (rápida), simplemente modifique su SQL ligeramente de la siguiente manera:
fuente
Antes de abrir la conexión a su base de datos, ejecute este código para cada una de sus clases de poco:
Luego agregue las anotaciones de datos a sus clases de poco como esta:
Después de eso, ya está todo listo. Simplemente haga una llamada de consulta, algo como:
fuente
Si está utilizando .NET 4.5.1 o superior, compruebe Dapper.FluentColumnMapping para mapear el estilo LINQ. Le permite separar completamente el mapeo db de su modelo (sin necesidad de anotaciones)
fuente
Esto es el respaldo de otras respuestas. Es solo un pensamiento que tenía para administrar las cadenas de consulta.
Person.cs
Método API
fuente
Para todos ustedes que usan Dapper 1.12, esto es lo que deben hacer para lograrlo:
y comentarlo
fuente
La solución de Kaleb Pederson funcionó para mí. Actualicé el ColumnAttributeTypeMapper para permitir un atributo personalizado (tenía requisitos para dos asignaciones diferentes en el mismo objeto de dominio) y propiedades actualizadas para permitir a los establecedores privados en los casos en que se necesitaba derivar un campo y los tipos diferían.
fuente
Sé que este es un hilo relativamente antiguo, pero pensé en tirar lo que hice allí.
Quería que la asignación de atributos funcionara globalmente. O coincide con el nombre de la propiedad (también conocido como predeterminado) o con un atributo de columna en la propiedad de la clase. Tampoco quería tener que configurar esto para cada clase a la que estaba asignando. Como tal, creé una clase DapperStart que invoco al inicio de la aplicación:
Bastante simple. No estoy seguro de qué problemas me encontraré todavía, ya que acabo de escribir esto, pero funciona.
fuente
CreateChatRequestResponse
sea reemplazado porT
cómo iteraría esto a través de todos los objetos de la Entidad. Por favor, corríjame si estoy equivocado.La solución simple al problema que Kaleb está tratando de resolver es simplemente aceptar el nombre de la propiedad si el atributo de columna no existe:
fuente