una obtener nombre name from encabezado columna column cambiar c# dapper dapper-rainbow

name - obtener nombre de columna datagridview c#



Apuesto. Asignar a la columna SQL con espacios en los nombres de columna (3)

Hay un paquete nuget Dapper.FluentMap que le permite agregar asignaciones de nombre de columna (incluidos los espacios). Es similar a EntityFramework.

// Entity class. public class Customer { public string Name { get; set; } } // Mapper class. public class CustomerMapper : EntityMap<Customer> { public CustomerMapper() { Map(p => p.Name).ToColumn("Customer Name"); } } // Initialise like so - FluentMapper.Initialize(a => a.AddMap(new CustomerMapper()));

vea https://github.com/henkmollema/Dapper-FluentMap para más información.

Me las arreglé para poner algo en marcha hoy como un pequeño proyecto de sandbox / POC, pero parece que me he topado con un problema ...

Pregunta:

¿Hay una manera de hacer que Dapper se asigne a los nombres de columna SQL con espacios en ellos?

Tengo algo en este sentido como mi conjunto de resultados.

Por ejemplo:

SELECT 001 AS [Col 1], 901 AS [Col 2], 00454345345345435349 AS [Col 3], 03453453453454353458 AS [Col 4] FROM [Some Schema].[Some Table]

Y mi clase se vería así.

public class ClassA { public string Col1 { get; set; } public string Col2 { get; set; } ///... etc }

Mi implementación se ve así en este momento.

public Tuple<IList<TClass>, IList<TClass2>> QueryMultiple<TClass, TClass2>(object parameters) { List<TClass> output1; List<TClass2> output2; using (var data = this.Connection.QueryMultiple(this.GlobalParameter.RpcProcedureName, parameters, CommandType.StoredProcedure)) { output1 = data.Read<TClass>().ToList(); output2 = data.Read<TClass2>().ToList(); } var result = new Tuple<IList<TClass>, IList<TClass2>>(output1, output2); return result; }

Nota: El SQL no puede ser modificado de ninguna manera.

Actualmente estoy revisando el código, y mi única solución previsible es agregar algo de código para "persuadir" a la comparación de columnas, pero hasta ahora no he tenido mucha suerte.

He visto en StackOverflow que hay cosas como extensiones dapper, pero espero poder hacer esto sin agregar una extensión, si no. Tomaré lo que sea más rápido de implementar.


Tuve un problema similar al intentar obtener resultados asignados de una llamada al procedimiento sp_spaceused del sistema. El código de Marc no funcionó para mí ya que se quejó de no poder encontrar un constructor predeterminado. También hice mi versión genérica para que, en teoría, pudiera ser reutilizada. Puede que este no sea el código de más rápido rendimiento, pero funciona para mí y, en nuestra situación, estas llamadas se hacen con poca frecuencia.

class TitleCaseMap<T> : SqlMapper.ITypeMap where T: new() { ConstructorInfo SqlMapper.ITypeMap.FindConstructor(string[] names, Type[] types) { return typeof(T).GetConstructor(Type.EmptyTypes); } SqlMapper.IMemberMap SqlMapper.ITypeMap.GetConstructorParameter(ConstructorInfo constructor, string columnName) { return null; } SqlMapper.IMemberMap SqlMapper.ITypeMap.GetMember(string columnName) { string reformattedColumnName = string.Empty; foreach (string word in columnName.Replace("_", " ").Split(new[] { '' '' }, StringSplitOptions.RemoveEmptyEntries)) { reformattedColumnName += char.ToUpper(word[0]) + word.Substring(1).ToLower(); } var prop = typeof(T).GetProperty(reformattedColumnName); return prop == null ? null : new PropertyMemberMap(prop); } class PropertyMemberMap : SqlMapper.IMemberMap { private readonly PropertyInfo _property; public PropertyMemberMap(PropertyInfo property) { _property = property; } string SqlMapper.IMemberMap.ColumnName { get { throw new NotImplementedException(); } } FieldInfo SqlMapper.IMemberMap.Field { get { return null; } } Type SqlMapper.IMemberMap.MemberType { get { return _property.PropertyType; } } ParameterInfo SqlMapper.IMemberMap.Parameter { get { return null; } } PropertyInfo SqlMapper.IMemberMap.Property { get { return _property; } } } }


Una opción aquí sería ir a través de la API dinámica / no genérica, y luego obtener los valores a través de la IDictionary<string,object> por fila, pero eso podría ser un poco tedioso.

Como alternativa, puede crear un mapeador personalizado y contarle a Dapper sobre ello; por ejemplo:

SqlMapper.SetTypeMap(typeof(ClassA), new RemoveSpacesMap());

con:

class RemoveSpacesMap : Dapper.SqlMapper.ITypeMap { System.Reflection.ConstructorInfo SqlMapper.ITypeMap.FindConstructor(string[] names, Type[] types) { return null; } SqlMapper.IMemberMap SqlMapper.ITypeMap.GetConstructorParameter(System.Reflection.ConstructorInfo constructor, string columnName) { return null; } SqlMapper.IMemberMap SqlMapper.ITypeMap.GetMember(string columnName) { var prop = typeof(ClassA).GetProperty(columnName.Replace(" ", "")); return prop == null ? null : new PropertyMemberMap(columnName, prop); } class PropertyMemberMap : Dapper.SqlMapper.IMemberMap { private string columnName; private PropertyInfo property; public PropertyMemberMap(string columnName, PropertyInfo property) { this.columnName = columnName; this.property = property; } string SqlMapper.IMemberMap.ColumnName { get { throw new NotImplementedException(); } } System.Reflection.FieldInfo SqlMapper.IMemberMap.Field { get { return null; } } Type SqlMapper.IMemberMap.MemberType { get { return property.PropertyType; } } System.Reflection.ParameterInfo SqlMapper.IMemberMap.Parameter { get { return null; } } System.Reflection.PropertyInfo SqlMapper.IMemberMap.Property { get { return property; } } } }