Saltar al contenido

Dapper con mapeo de atributos

El tutorial o código que encontrarás en este post es la solución más eficiente y válida que hallamos a esta inquietud o problema.

Solución:

Para completar la solución, quiero compartir el código que encontré y juntar con aquellos que estén interesados.

En lugar de (ab) usar System.Data.Linq.Mapping.ColumnAttribute, podría ser más lógico (y probablemente guardar, aunque la posibilidad será muy pequeña de que Microsoft cambie la clase linq a sql ColumnAttribute) para crear nuestro propio ColumnAttribute clase:

ColumnAttribute.cs

using System;

namespace DapperTestProj.DapperAttributeMapper //Maybe a better namespace here
 AttributeTargets.Property)]
    public class ColumnAttribute : Attribute
    
        public string Name  get; set; 

        public ColumnAttribute(string name)
        
            Name = name;
        
    

Encontrado en el tema que mencioné anteriormente, las clases FallBackTypeMapper y ColumnAttributeTypeMapper:

FallBackTypeMapper.cs

using System;
using System.Collections.Generic;
using System.Reflection;
using Dapper;

namespace DapperTestProj.DapperAttributeMapper

    public class FallBackTypeMapper : SqlMapper.ITypeMap
    
        private readonly IEnumerable _mappers;

        public FallBackTypeMapper(IEnumerable mappers)
        
            _mappers = mappers;
        

        public ConstructorInfo FindConstructor(string[] names, Type[] types)
        
            foreach (var mapper in _mappers)
            
                try
                
                    var result = mapper.FindConstructor(names, types);

                    if (result != null)
                    
                        return result;
                    
                
                catch (NotImplementedException nix)
                
                    // the CustomPropertyTypeMap only supports a no-args
                    // constructor and throws a not implemented exception.
                    // to work around that, catch and ignore.
                
            
            return null;
        

        public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
        
            foreach (var mapper in _mappers)
            
                try
                
                    var result = mapper.GetConstructorParameter(constructor, columnName);

                    if (result != null)
                    
                        return result;
                    
                
                catch (NotImplementedException nix)
                
                    // the CustomPropertyTypeMap only supports a no-args
                    // constructor and throws a not implemented exception.
                    // to work around that, catch and ignore.
                
            
            return null;
        

        public SqlMapper.IMemberMap GetMember(string columnName)
        
            foreach (var mapper in _mappers)
            
                try
                
                    var result = mapper.GetMember(columnName);

                    if (result != null)
                    
                        return result;
                    
                
                catch (NotImplementedException nix)
                
                    // the CustomPropertyTypeMap only supports a no-args
                    // constructor and throws a not implemented exception.
                    // to work around that, catch and ignore.
                
            
            return null;
        
    

ColumnAttributeTypeMapper.cs

using System.Linq;
using Dapper;

namespace DapperTestProj.DapperAttributeMapper

    public class ColumnAttributeTypeMapper : FallBackTypeMapper
    
        public ColumnAttributeTypeMapper()
            : base(new SqlMapper.ITypeMap[]
                    
                        new CustomPropertyTypeMap(typeof(T),
                            (type, columnName) =>
                                type.GetProperties().FirstOrDefault(prop =>
                                    prop.GetCustomAttributes(false)
                                        .OfType()
                                        .Any(attribute => attribute.Name == columnName)
                            )
                        ),
                        new DefaultTypeMap(typeof(T)) 
                    )
        
        
    

y finalmente, el TypeMapper.cs para inicializar el mapeo.

using System;
using System.Linq;
using System.Reflection;
using Dapper;

namespace DapperTestProj.DapperAttributeMapper

    public static class TypeMapper
    
        public static void Initialize(string @namespace)
        
            var types = from assem in AppDomain.CurrentDomain.GetAssemblies().ToList()
                    from type in assem.GetTypes()
                    where type.IsClass && type.Namespace == @namespace
                    select type;

            types.ToList().ForEach(type =>
            
                var mapper = (SqlMapper.ITypeMap)Activator
                    .CreateInstance(typeof(ColumnAttributeTypeMapper<>)
                                    .MakeGenericType(type));
                SqlMapper.SetTypeMap(type, mapper);
            );
        
    

Al inicio, se debe llamar a TypeMapper.Initialize:

TypeMapper.Initialize("DapperTestProj.Entities");

Y puedes empezar a usar attributes para las propiedades de la entidad

using DapperTestProj.DapperAttributeMapper;

namespace DapperTestProj.Entities

    public class Table1
    
        [Column("Table1Id")]
        public int Id  get; set; 

        public string Column1  get; set; 

        public string Column2  get; set; 

        public Table2 Table2  get; set; 

        public Table1()
        
            Table2 = new Table2();
        
    

La respuesta de Cornelis es correcta, sin embargo, quería agregar una actualización a esto. A partir de la versión actual de Dapper, también debe implementar SqlMapper.ItypeMap.FindExplicitConstructor(). No estoy seguro de cuándo se realizó este cambio, pero esto para cualquier otra persona que se encuentre con esta pregunta y no tenga esa parte de la solución.

Dentro de FallbackTypeMapper.cs

public ConstructorInfo FindExplicitConstructor()

    return _mappers.Select(m => m.FindExplicitConstructor())
        .FirstOrDefault(result => result != null);

También puede utilizar el ColumnAttribute clase ubicada dentro del System.ComponentModel.DataAnnotations.Schema espacio de nombres en lugar de rodar el suyo propio para una versión integrada que no sea de base de datos / orm.

valoraciones y reseñas

Si posees algún aprieto o capacidad de arreglar nuestro ensayo puedes realizar una crítica y con gusto lo observaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *